mirror of
https://github.com/docker/compose.git
synced 2026-02-10 02:29:25 +08:00
Compare commits
626 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
00bd108aec | ||
|
|
792afb8d13 | ||
|
|
150449bbd2 | ||
|
|
8d0df18762 | ||
|
|
5b53f8e47f | ||
|
|
c5fef61383 | ||
|
|
ce3cb2b00c | ||
|
|
d9e73db8e6 | ||
|
|
d6b4d1c755 | ||
|
|
0baf24a269 | ||
|
|
0511b0c2b8 | ||
|
|
5bbdf3d84a | ||
|
|
52103cce74 | ||
|
|
020b57ca31 | ||
|
|
bfa54081d4 | ||
|
|
0be8e4a676 | ||
|
|
fd8ab2f7ac | ||
|
|
b406b393bf | ||
|
|
0a9d1277c5 | ||
|
|
c350f80d4b | ||
|
|
8a4095b507 | ||
|
|
0345461412 | ||
|
|
80856eacaf | ||
|
|
d7b1972d5e | ||
|
|
7c42776770 | ||
|
|
3b0742fd57 | ||
|
|
efd44de1b7 | ||
|
|
bdb3f91eb4 | ||
|
|
f94cb49062 | ||
|
|
e7ed070690 | ||
|
|
8a1bf5d28b | ||
|
|
7ef392004f | ||
|
|
f34f5b4d26 | ||
|
|
b0484700da | ||
|
|
f65fd02383 | ||
|
|
cf8dc46560 | ||
|
|
2cfbe63533 | ||
|
|
8318f66330 | ||
|
|
cb17c3c8a6 | ||
|
|
9174a99d27 | ||
|
|
4eb43c53fa | ||
|
|
150b88ab5d | ||
|
|
5159058c7e | ||
|
|
1ae191a936 | ||
|
|
3b2f3cdce3 | ||
|
|
47778f8b77 | ||
|
|
7d88edaf24 | ||
|
|
636c13f818 | ||
|
|
5a072b1ad5 | ||
|
|
ddceb1ac9d | ||
|
|
d48f28c72c | ||
|
|
2d16a05afa | ||
|
|
bb94ea034e | ||
|
|
0938c7e96f | ||
|
|
f429ee958a | ||
|
|
e9ded2c518 | ||
|
|
54e6e0bd8f | ||
|
|
3bc871e64b | ||
|
|
6ff15d9472 | ||
|
|
49bc0603e3 | ||
|
|
ce8a09b53f | ||
|
|
3dc8734897 | ||
|
|
852e192820 | ||
|
|
d9e7859664 | ||
|
|
e28b223650 | ||
|
|
1964693074 | ||
|
|
dc74e6aa0e | ||
|
|
b182cf6850 | ||
|
|
f330b24632 | ||
|
|
8339269e13 | ||
|
|
ee6aeed84e | ||
|
|
7a9dfa4284 | ||
|
|
29daae3d6e | ||
|
|
8dea7b5cae | ||
|
|
bc6ad2e4a4 | ||
|
|
e6a7694b8d | ||
|
|
46d936c750 | ||
|
|
15bc7850bb | ||
|
|
8a64ab56a0 | ||
|
|
1178c51e6a | ||
|
|
3b3fd3e56c | ||
|
|
b1e10f559e | ||
|
|
baea5a48f5 | ||
|
|
cb3a6ce52b | ||
|
|
28f3802a07 | ||
|
|
fd0e0a2cbd | ||
|
|
e90df62bb0 | ||
|
|
b0af2deb2b | ||
|
|
be22bc735a | ||
|
|
b5f5e27597 | ||
|
|
b1334b8dfc | ||
|
|
25ca75db4d | ||
|
|
827e864ed0 | ||
|
|
28301fb1a4 | ||
|
|
fa3e16c66b | ||
|
|
edd76bfd70 | ||
|
|
c496c23071 | ||
|
|
02284378bf | ||
|
|
10b290e682 | ||
|
|
3906a7a67c | ||
|
|
83671db3dd | ||
|
|
1a41678c58 | ||
|
|
035276e027 | ||
|
|
db24023884 | ||
|
|
c48f542962 | ||
|
|
42dc7a6a87 | ||
|
|
30b3b47383 | ||
|
|
061b52da9a | ||
|
|
04aa155878 | ||
|
|
2d4f8d31fc | ||
|
|
e1f8603a62 | ||
|
|
a2ce602f6c | ||
|
|
401334e03f | ||
|
|
93cf2b921a | ||
|
|
83b2433a27 | ||
|
|
c8d06137b5 | ||
|
|
c61b8aa5ac | ||
|
|
ff3984e609 | ||
|
|
2efea2e9f5 | ||
|
|
6a3a95c4a8 | ||
|
|
fee8a1c6c6 | ||
|
|
7ffe83dc95 | ||
|
|
d20c2551f2 | ||
|
|
0e9a5b6b78 | ||
|
|
6887a3fc3e | ||
|
|
586fe87f98 | ||
|
|
6d66130266 | ||
|
|
0f83a8630e | ||
|
|
26cb941f79 | ||
|
|
43783d36e2 | ||
|
|
08e6bfc859 | ||
|
|
7a870e2449 | ||
|
|
8cd8f08d77 | ||
|
|
cfe91becc7 | ||
|
|
9384e5f4d7 | ||
|
|
68bd0eb523 | ||
|
|
3fe665b93d | ||
|
|
508d71c5df | ||
|
|
58c5ea8217 | ||
|
|
ec31d3c2ac | ||
|
|
599723f890 | ||
|
|
0a9b9fd8fe | ||
|
|
3c8a56dbf3 | ||
|
|
e63ab14b1e | ||
|
|
32cf776ecd | ||
|
|
955784c406 | ||
|
|
2d22c2b5ce | ||
|
|
852c9e80b4 | ||
|
|
37850f7955 | ||
|
|
4bf2fe9fed | ||
|
|
e21a8d6293 | ||
|
|
f8b6459403 | ||
|
|
be6c9565e3 | ||
|
|
60fe97416c | ||
|
|
629c9f62e9 | ||
|
|
7c3fe359b7 | ||
|
|
d2aa15c06e | ||
|
|
6530880361 | ||
|
|
1bd8a773a7 | ||
|
|
fed8ef6b79 | ||
|
|
419fcdd6c8 | ||
|
|
65b714c108 | ||
|
|
44dd232e97 | ||
|
|
83ad5e97b7 | ||
|
|
b0a35ccc98 | ||
|
|
f5480ee3ed | ||
|
|
b4924dee83 | ||
|
|
2ca8ab914a | ||
|
|
3ec8c60657 | ||
|
|
06ec06472f | ||
|
|
466e1d3197 | ||
|
|
0d6b99e6f9 | ||
|
|
01d91c490c | ||
|
|
6f6e1635fd | ||
|
|
3d05a1becf | ||
|
|
42cd961d58 | ||
|
|
d15fcc6444 | ||
|
|
22c2471a08 | ||
|
|
29a1cc452d | ||
|
|
b05a94fd66 | ||
|
|
15cad92b61 | ||
|
|
c7afc6188b | ||
|
|
ca19b7fcc9 | ||
|
|
93bd27a0cc | ||
|
|
68c462e607 | ||
|
|
916aac6c27 | ||
|
|
eafcd1b35e | ||
|
|
1e399c271a | ||
|
|
544b579cb0 | ||
|
|
daa6bec80a | ||
|
|
34bd41cc0c | ||
|
|
70953b18c0 | ||
|
|
cfe1a860ff | ||
|
|
4dcda432cf | ||
|
|
5c2a885647 | ||
|
|
cd0fc214a5 | ||
|
|
9b5a4588f9 | ||
|
|
00f72cb553 | ||
|
|
fd7847f2ac | ||
|
|
18a112e88c | ||
|
|
dc01b98aa6 | ||
|
|
312f0d1d61 | ||
|
|
e8caad1903 | ||
|
|
fca454b41f | ||
|
|
77dc9b54f3 | ||
|
|
bceb3c1876 | ||
|
|
a14abb9044 | ||
|
|
0363d9260a | ||
|
|
0e375a8c61 | ||
|
|
b776826d92 | ||
|
|
3b32a264c7 | ||
|
|
e92c5d1392 | ||
|
|
0c1a691fa5 | ||
|
|
f72d5d6099 | ||
|
|
ee70085fba | ||
|
|
90bcf610b3 | ||
|
|
2d25019fe9 | ||
|
|
fb16e49cb2 | ||
|
|
109ce190c4 | ||
|
|
ef03c906b9 | ||
|
|
865a0867a4 | ||
|
|
6ee0376bb6 | ||
|
|
67455e9f33 | ||
|
|
5fdcaa0fe1 | ||
|
|
01afe5265e | ||
|
|
2e4faf80f5 | ||
|
|
e88836ffbd | ||
|
|
b45ca82791 | ||
|
|
d1c36c6e6b | ||
|
|
b304c4e154 | ||
|
|
eca1365d42 | ||
|
|
03f4c0e631 | ||
|
|
2a0e83ad9a | ||
|
|
2df9919ece | ||
|
|
74fc40d895 | ||
|
|
d54a95fed7 | ||
|
|
c1369869f5 | ||
|
|
f5ff40a2f3 | ||
|
|
6347b49f9c | ||
|
|
c072a6f5f5 | ||
|
|
a06d32e7b6 | ||
|
|
28fa309c23 | ||
|
|
4f2c933f78 | ||
|
|
e22c8964b9 | ||
|
|
07c4849cb9 | ||
|
|
e606701d9f | ||
|
|
114e5c6425 | ||
|
|
37dfb5bf26 | ||
|
|
d01ef5887a | ||
|
|
dec608f3cd | ||
|
|
eb0632b1d8 | ||
|
|
1383ab09ec | ||
|
|
5eaafe4237 | ||
|
|
7840a92c40 | ||
|
|
3751c3074b | ||
|
|
2bc6a45c0b | ||
|
|
2268d1e573 | ||
|
|
7b0ed13209 | ||
|
|
d4441efe1e | ||
|
|
58368f69e9 | ||
|
|
bc2b2e52e5 | ||
|
|
7723d11930 | ||
|
|
65fda18821 | ||
|
|
0e7e1b940b | ||
|
|
af6f0ffb9e | ||
|
|
9ef173a3ac | ||
|
|
1fb0c03e8b | ||
|
|
1892be8c70 | ||
|
|
37068a700f | ||
|
|
a4af5e229d | ||
|
|
87da6c1470 | ||
|
|
a99acd940a | ||
|
|
7fb87856aa | ||
|
|
eb933adde0 | ||
|
|
cb688b5fd4 | ||
|
|
8b5b78fbb6 | ||
|
|
d3e49fe360 | ||
|
|
1bca8d5c01 | ||
|
|
76d9cf2711 | ||
|
|
d762f5f473 | ||
|
|
90eda35f3d | ||
|
|
7ce0096f40 | ||
|
|
00eca0af70 | ||
|
|
a10c4c6df5 | ||
|
|
6a37428491 | ||
|
|
449a46a252 | ||
|
|
981cb2024e | ||
|
|
b83edbd039 | ||
|
|
02ad467f89 | ||
|
|
d9e1d419c1 | ||
|
|
a4c324b8e6 | ||
|
|
087fae98b6 | ||
|
|
aafeaa66e2 | ||
|
|
c5317496ac | ||
|
|
67c9ecb4f4 | ||
|
|
72a61c0602 | ||
|
|
0b6133f75b | ||
|
|
b24af42bcc | ||
|
|
cc70851bc8 | ||
|
|
3b85cd2fa9 | ||
|
|
d818bf6f34 | ||
|
|
45a852f438 | ||
|
|
f0bf4fca76 | ||
|
|
cd17c8a950 | ||
|
|
36625ed229 | ||
|
|
a6ffdf6110 | ||
|
|
72260d615d | ||
|
|
fd28ab8d38 | ||
|
|
9ab5d8c44e | ||
|
|
d637cc3ade | ||
|
|
925bc6fbf3 | ||
|
|
16d5354d70 | ||
|
|
7aaea283ca | ||
|
|
6bedc196cc | ||
|
|
a11515e038 | ||
|
|
6c1f06e420 | ||
|
|
88b0d17ff8 | ||
|
|
9e19bc8441 | ||
|
|
bef9c48a1a | ||
|
|
105a7c5b70 | ||
|
|
03f0ed132d | ||
|
|
f7a13aee11 | ||
|
|
bfeb1dc277 | ||
|
|
9ec43973e2 | ||
|
|
0b41df9821 | ||
|
|
643557d534 | ||
|
|
200f47e5be | ||
|
|
e0aaccf430 | ||
|
|
754c06886f | ||
|
|
e492330dd5 | ||
|
|
bbe1b77a67 | ||
|
|
fc4d2dfdd8 | ||
|
|
85ddfde5d6 | ||
|
|
6a0398d786 | ||
|
|
4434cea535 | ||
|
|
62fbf20887 | ||
|
|
3f7d3c2661 | ||
|
|
9cc1613b55 | ||
|
|
c4b47fe911 | ||
|
|
167c6a89b1 | ||
|
|
a84345be8f | ||
|
|
3cfbac6624 | ||
|
|
a3bed265f2 | ||
|
|
ae26426cc8 | ||
|
|
4ea44797f5 | ||
|
|
a99a0b50ef | ||
|
|
af414e9e2c | ||
|
|
89633748d2 | ||
|
|
f648c2949b | ||
|
|
33aa6acefe | ||
|
|
e31b95c16d | ||
|
|
d4f156cc7d | ||
|
|
c0daf8d3b5 | ||
|
|
7bb60d091c | ||
|
|
da1ca578b5 | ||
|
|
267cde91df | ||
|
|
18af72af87 | ||
|
|
e831ea826b | ||
|
|
8d56db5e1d | ||
|
|
1edc64ef93 | ||
|
|
156e54a09e | ||
|
|
762cf9d998 | ||
|
|
f3e543fd6a | ||
|
|
9732608ec2 | ||
|
|
24ff098252 | ||
|
|
593c4263f3 | ||
|
|
313b82e94c | ||
|
|
5e3e2171d4 | ||
|
|
9ac0392baf | ||
|
|
0612b34c68 | ||
|
|
92e0cd4047 | ||
|
|
1a410ffe30 | ||
|
|
282a29e67e | ||
|
|
256ec49974 | ||
|
|
9765f171cd | ||
|
|
b19df5c96c | ||
|
|
7a42ba7eec | ||
|
|
5b043c4d59 | ||
|
|
d93da187f2 | ||
|
|
15f7104cd3 | ||
|
|
eb1c798912 | ||
|
|
78b9404767 | ||
|
|
25be264ed8 | ||
|
|
e6e2f7839f | ||
|
|
7532f76986 | ||
|
|
70ab9f8f33 | ||
|
|
7daa2a5325 | ||
|
|
93bffd9a7f | ||
|
|
9a4e74c70c | ||
|
|
52478f0c6e | ||
|
|
b5f0a4eefa | ||
|
|
e908f41ec8 | ||
|
|
0f5b5ccbd0 | ||
|
|
a2d36b6c6c | ||
|
|
b3ec110612 | ||
|
|
3077234292 | ||
|
|
23585b9e6d | ||
|
|
fdc1738143 | ||
|
|
2336d9fe35 | ||
|
|
bf0ed9a4d4 | ||
|
|
1640f155e9 | ||
|
|
e63cbfba0e | ||
|
|
25576289c8 | ||
|
|
7d6ee74e62 | ||
|
|
c08e07714a | ||
|
|
cf31462398 | ||
|
|
1b71e3efb3 | ||
|
|
4d822676ce | ||
|
|
6fc0b6ff27 | ||
|
|
ab84b6ac5b | ||
|
|
7161778ccf | ||
|
|
1f5bfe8882 | ||
|
|
f79c75ab10 | ||
|
|
e62993a854 | ||
|
|
28251e8be5 | ||
|
|
c7ba7d9de5 | ||
|
|
8b39322365 | ||
|
|
b3615d64e2 | ||
|
|
1a1d1707ed | ||
|
|
fd3e0bbe2b | ||
|
|
d2d4d05264 | ||
|
|
dda0362b6e | ||
|
|
ddc88ec41b | ||
|
|
92c6a65a03 | ||
|
|
00b3caecbb | ||
|
|
17087447e9 | ||
|
|
ec781687fd | ||
|
|
b22dde9f18 | ||
|
|
a31350ede1 | ||
|
|
d744c97f13 | ||
|
|
37647bc600 | ||
|
|
21e5d564af | ||
|
|
390d5cf165 | ||
|
|
7f6e189dbc | ||
|
|
b5ccea7b0e | ||
|
|
47551895f3 | ||
|
|
5e0f1eec16 | ||
|
|
f82e2de57e | ||
|
|
9c7f7bc0fa | ||
|
|
6defe7cac6 | ||
|
|
0482f9276a | ||
|
|
e8a34c8d1e | ||
|
|
9e261c18b3 | ||
|
|
1fd7ca5440 | ||
|
|
139edc403f | ||
|
|
38b3f3b678 | ||
|
|
c5bce8bd42 | ||
|
|
c8a358a455 | ||
|
|
a6701652d2 | ||
|
|
4562b0bf95 | ||
|
|
4801d2b1a4 | ||
|
|
3850a34114 | ||
|
|
664e6f6f23 | ||
|
|
d4f074b32f | ||
|
|
a3b012d89f | ||
|
|
a755c84ea0 | ||
|
|
ef34a38ac0 | ||
|
|
f24d3458c6 | ||
|
|
41e056341b | ||
|
|
a54d488303 | ||
|
|
c0b4dd8606 | ||
|
|
6754c6b68a | ||
|
|
a93f09efac | ||
|
|
bbf3ec1999 | ||
|
|
51bcfa37bd | ||
|
|
982a8ccb88 | ||
|
|
790712fa92 | ||
|
|
97752b23e8 | ||
|
|
69c0a583be | ||
|
|
8bb9a3336d | ||
|
|
634a7d2a7b | ||
|
|
cf12239547 | ||
|
|
a288332fbd | ||
|
|
9d53ed8f63 | ||
|
|
df70735295 | ||
|
|
d8bf175cd4 | ||
|
|
4816f40b90 | ||
|
|
ed5a2e83c7 | ||
|
|
fa8d075d88 | ||
|
|
33c3f4dfad | ||
|
|
aa31387355 | ||
|
|
d47f0f31c2 | ||
|
|
ac8ab8634a | ||
|
|
4721c01702 | ||
|
|
5919fcb4cd | ||
|
|
4671e69a96 | ||
|
|
3a21e1e319 | ||
|
|
b670aefb94 | ||
|
|
d5d9f67547 | ||
|
|
a2899d5ff0 | ||
|
|
220626ec5e | ||
|
|
6c795d60bf | ||
|
|
291e1bd618 | ||
|
|
e94eb056b4 | ||
|
|
c15bf1955a | ||
|
|
0b1c86726e | ||
|
|
82ef998511 | ||
|
|
fb36f7fffd | ||
|
|
3fac506a30 | ||
|
|
eb59b0e265 | ||
|
|
5081ab0507 | ||
|
|
13ef440d6a | ||
|
|
fbf845c5f8 | ||
|
|
5a2b7b83cd | ||
|
|
8c07fa4d25 | ||
|
|
db267d86c1 | ||
|
|
9daf41892f | ||
|
|
2aa88b5c9e | ||
|
|
bb9cf32245 | ||
|
|
7212aaff2e | ||
|
|
69a09624c9 | ||
|
|
f2088bb917 | ||
|
|
dadad01e63 | ||
|
|
1adc9f54d5 | ||
|
|
4cebce3a5c | ||
|
|
bd8e57447a | ||
|
|
4ad87463c5 | ||
|
|
62b3e7409e | ||
|
|
cc912c625d | ||
|
|
cc7e69c02d | ||
|
|
3e12a7cb23 | ||
|
|
0c1979979f | ||
|
|
00c60da331 | ||
|
|
73ebbffb08 | ||
|
|
fbbc0dedcf | ||
|
|
b326a9da1d | ||
|
|
f1313f3a09 | ||
|
|
a226d014b8 | ||
|
|
7e2af3aa81 | ||
|
|
96bbda98f8 | ||
|
|
f6f29a4438 | ||
|
|
aa5cdf2bf9 | ||
|
|
d5e4f00644 | ||
|
|
8b4ac37f9c | ||
|
|
b96e27e0e7 | ||
|
|
dcbd68a102 | ||
|
|
37d15d7e6b | ||
|
|
dde7eea212 | ||
|
|
a224780795 | ||
|
|
ffce33ec11 | ||
|
|
1d9657aee2 | ||
|
|
8a3248d0cd | ||
|
|
52e7f0fb3e | ||
|
|
fd353ffa94 | ||
|
|
0307c16daf | ||
|
|
adf8e75317 | ||
|
|
6c537cc0f4 | ||
|
|
9f7ad18d62 | ||
|
|
40ebcd6203 | ||
|
|
9bd9f1765c | ||
|
|
5dcadc05d9 | ||
|
|
c72f161afb | ||
|
|
86a648bd51 | ||
|
|
27a3241934 | ||
|
|
935968fe2c | ||
|
|
91371fef7a | ||
|
|
986bc44549 | ||
|
|
24f83271f2 | ||
|
|
dacf24374d | ||
|
|
bab3050984 | ||
|
|
22d2e83896 | ||
|
|
9f5f0b6f03 | ||
|
|
b4b7319901 | ||
|
|
ab791877ef | ||
|
|
aae5ddca27 | ||
|
|
7cf6d5ec4e | ||
|
|
0ab5079c1a | ||
|
|
89ef8198f3 | ||
|
|
b8bbdcd872 | ||
|
|
9d12eec148 | ||
|
|
d0e95ccac3 | ||
|
|
1e682a40ac | ||
|
|
7bc27d441b | ||
|
|
c1ce53c972 | ||
|
|
e42673daed | ||
|
|
c37182b2c5 | ||
|
|
ffb95449a2 | ||
|
|
0eaa249222 | ||
|
|
5c1484ece6 | ||
|
|
0fedddb008 | ||
|
|
aa0720f7e5 | ||
|
|
84984864c8 | ||
|
|
8566daa96e | ||
|
|
1b1f783e99 | ||
|
|
84ea395d5d | ||
|
|
1cb5536a2e | ||
|
|
e4850d9c48 | ||
|
|
8c39b5b7fd | ||
|
|
bc568eeb9b | ||
|
|
a501ab3a2f | ||
|
|
d4a4dcf4ee | ||
|
|
05e987dd0a | ||
|
|
0368f19030 | ||
|
|
3ee2ab87bb | ||
|
|
8f991a20db | ||
|
|
0234e13454 | ||
|
|
c342891f3e | ||
|
|
40fb42e0c9 | ||
|
|
8ef3494711 | ||
|
|
be74c90f50 | ||
|
|
cc247fdb84 | ||
|
|
a4ac6ab694 | ||
|
|
a5823b12f9 | ||
|
|
b27ace6c55 | ||
|
|
a73dce44b3 | ||
|
|
804d7163a7 | ||
|
|
cc60026c7b | ||
|
|
6b4ad0d1db | ||
|
|
87a0a57f70 | ||
|
|
c80d52aded | ||
|
|
95bc6c58b7 | ||
|
|
be30c67633 | ||
|
|
57a1e1e0df | ||
|
|
02305756b3 | ||
|
|
12dad4f8d0 | ||
|
|
a0acc20d88 | ||
|
|
053f20edab | ||
|
|
6fae6a41f9 | ||
|
|
dd5ea044bb | ||
|
|
12de97b8d1 | ||
|
|
62b5f78fd9 | ||
|
|
3f526c5c7b | ||
|
|
12916b75a2 | ||
|
|
e3948f6bae | ||
|
|
91a2bdd6de | ||
|
|
ce61e7bf18 |
18
.github/dependabot.yml
vendored
18
.github/dependabot.yml
vendored
@@ -5,14 +5,20 @@ updates:
|
||||
schedule:
|
||||
interval: daily
|
||||
ignore:
|
||||
# docker/buildx + docker/cli + docker/docker require coordination to
|
||||
# ensure compatibility between them
|
||||
# docker + moby deps require coordination
|
||||
- dependency-name: "github.com/docker/buildx"
|
||||
# buildx is still 0.x
|
||||
update-types: ["version-update:semver-minor"]
|
||||
- dependency-name: "github.com/moby/buildkit"
|
||||
# buildkit is still 0.x
|
||||
update-types: [ "version-update:semver-minor" ]
|
||||
- dependency-name: "github.com/docker/cli"
|
||||
# docker/cli uses CalVer rather than SemVer
|
||||
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: "github.com/docker/docker"
|
||||
# docker/docker uses CalVer rather than SemVer
|
||||
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
||||
update-types: ["version-update:semver-major"]
|
||||
- dependency-name: "github.com/containerd/containerd"
|
||||
# containerd major/minor must be kept in sync with moby
|
||||
update-types: [ "version-update:semver-major", "version-update:semver-minor" ]
|
||||
- dependency-name: "go.opentelemetry.io/otel/*"
|
||||
# OTEL is v1.x but has some parts that are not API stable yet
|
||||
update-types: [ "version-update:semver-major", "version-update:semver-minor"]
|
||||
|
||||
88
.github/workflows/ci.yml
vendored
88
.github/workflows/ci.yml
vendored
@@ -7,7 +7,7 @@ concurrency:
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'v2'
|
||||
- 'main'
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
@@ -19,7 +19,6 @@ on:
|
||||
default: "false"
|
||||
|
||||
env:
|
||||
DESTDIR: "./bin"
|
||||
DOCKER_CLI_VERSION: "20.10.17"
|
||||
|
||||
permissions:
|
||||
@@ -38,7 +37,7 @@ jobs:
|
||||
name: Create matrix
|
||||
id: platforms
|
||||
run: |
|
||||
echo ::set-output name=matrix::$(docker buildx bake binary-cross --print | jq -cr '.target."binary-cross".platforms')
|
||||
echo matrix=$(docker buildx bake binary-cross --print | jq -cr '.target."binary-cross".platforms') >> $GITHUB_OUTPUT
|
||||
-
|
||||
name: Show matrix
|
||||
run: |
|
||||
@@ -52,7 +51,6 @@ jobs:
|
||||
target:
|
||||
- lint
|
||||
- validate-go-mod
|
||||
- validate-modules
|
||||
- validate-headers
|
||||
- validate-docs
|
||||
steps:
|
||||
@@ -104,7 +102,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: compose
|
||||
path: ${{ env.DESTDIR }}/*
|
||||
path: ./bin/release/*
|
||||
if-no-files-found: error
|
||||
|
||||
test:
|
||||
@@ -124,17 +122,23 @@ jobs:
|
||||
set: |
|
||||
*.cache-from=type=gha,scope=test
|
||||
*.cache-to=type=gha,scope=test
|
||||
-
|
||||
name: Gather coverage data
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-data-unit
|
||||
path: bin/coverage/unit/
|
||||
if-no-files-found: error
|
||||
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DESTDIR: "./bin/build"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
mode:
|
||||
- plugin
|
||||
- standalone
|
||||
- cucumber
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
@@ -158,7 +162,7 @@ jobs:
|
||||
name: Build
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: binary
|
||||
targets: binary-with-coverage
|
||||
set: |
|
||||
*.cache-from=type=gha,scope=binary-linux-amd64
|
||||
*.cache-from=type=gha,scope=binary-e2e-${{ matrix.mode }}
|
||||
@@ -176,10 +180,17 @@ jobs:
|
||||
name: Test plugin mode
|
||||
if: ${{ matrix.mode == 'plugin' }}
|
||||
run: |
|
||||
make e2e-compose
|
||||
rm -rf ./bin/coverage/e2e
|
||||
mkdir -p ./bin/coverage/e2e
|
||||
make e2e-compose GOCOVERDIR=bin/coverage/e2e TEST_FLAGS="-v"
|
||||
-
|
||||
name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
name: Gather coverage data
|
||||
if: ${{ matrix.mode == 'plugin' }}
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: coverage-data-e2e
|
||||
path: bin/coverage/e2e/
|
||||
if-no-files-found: error
|
||||
-
|
||||
name: Test standalone mode
|
||||
if: ${{ matrix.mode == 'standalone' }}
|
||||
@@ -187,6 +198,49 @@ jobs:
|
||||
rm -f /usr/local/bin/docker-compose
|
||||
cp bin/build/docker-compose /usr/local/bin
|
||||
make e2e-compose-standalone
|
||||
-
|
||||
name: Run cucumber tests
|
||||
if: ${{ matrix.mode == 'cucumber'}}
|
||||
run: |
|
||||
make test-cucumber
|
||||
|
||||
coverage:
|
||||
runs-on: ubuntu-22.04
|
||||
needs:
|
||||
- test
|
||||
- e2e
|
||||
steps:
|
||||
# codecov won't process the report without the source code available
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version-file: 'go.mod'
|
||||
check-latest: true
|
||||
- name: Download unit test coverage
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: coverage-data-unit
|
||||
path: coverage/unit
|
||||
- name: Download E2E test coverage
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: coverage-data-e2e
|
||||
path: coverage/e2e
|
||||
- name: Merge coverage reports
|
||||
run: |
|
||||
go tool covdata textfmt -i=./coverage/unit,./coverage/e2e -o ./coverage.txt
|
||||
- name: Store coverage report in GitHub Actions
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: go-covdata-txt
|
||||
path: ./coverage.txt
|
||||
if-no-files-found: error
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./coverage.txt
|
||||
|
||||
release:
|
||||
permissions:
|
||||
@@ -204,10 +258,10 @@ jobs:
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: compose
|
||||
path: ${{ env.DESTDIR }}
|
||||
path: bin/release
|
||||
-
|
||||
name: Create checksums
|
||||
working-directory: ${{ env.DESTDIR }}
|
||||
working-directory: bin/release
|
||||
run: |
|
||||
find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# \*\./# *#' > $RUNNER_TEMP/checksums.txt
|
||||
shasum -a 256 -U -c $RUNNER_TEMP/checksums.txt
|
||||
@@ -215,21 +269,21 @@ jobs:
|
||||
cat checksums.txt | while read sum file; do echo "$sum $file" > ${file#\*}.sha256; done
|
||||
-
|
||||
name: License
|
||||
run: cp packaging/* ${{ env.DESTDIR }}/
|
||||
run: cp packaging/* bin/release/
|
||||
-
|
||||
name: List artifacts
|
||||
run: |
|
||||
tree -nh ${{ env.DESTDIR }}
|
||||
tree -nh bin/release
|
||||
-
|
||||
name: Check artifacts
|
||||
run: |
|
||||
find ${{ env.DESTDIR }} -type f -exec file -e ascii -- {} +
|
||||
find bin/release -type f -exec file -e ascii -- {} +
|
||||
-
|
||||
name: GitHub Release
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # v1.10.0
|
||||
with:
|
||||
artifacts: ${{ env.DESTDIR }}/*
|
||||
artifacts: bin/release/*
|
||||
generateReleaseNotes: true
|
||||
draft: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
81
.github/workflows/merge.yml
vendored
81
.github/workflows/merge.yml
vendored
@@ -7,14 +7,16 @@ concurrency:
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'v2'
|
||||
- 'main'
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read # to fetch code (actions/checkout)
|
||||
|
||||
env:
|
||||
REPO_SLUG: "docker/compose-bin"
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
name: Build and test
|
||||
@@ -72,3 +74,78 @@ jobs:
|
||||
run: |
|
||||
make e2e-compose-standalone
|
||||
|
||||
bin-image:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
digest: ${{ fromJSON(steps.bake.outputs.metadata).image-cross['containerimage.digest'] }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: |
|
||||
${{ env.REPO_SLUG }}
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
type=edge
|
||||
bake-target: meta-helper
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERPUBLICBOT_USERNAME }}
|
||||
password: ${{ secrets.DOCKERPUBLICBOT_WRITE_PAT }}
|
||||
-
|
||||
name: Build and push image
|
||||
uses: docker/bake-action@v2
|
||||
id: bake
|
||||
with:
|
||||
files: |
|
||||
./docker-bake.hcl
|
||||
${{ steps.meta.outputs.bake-file }}
|
||||
targets: image-cross
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
set: |
|
||||
*.cache-from=type=gha,scope=bin-image
|
||||
*.cache-to=type=gha,scope=bin-image,mode=max
|
||||
*.attest=type=sbom
|
||||
*.attest=type=provenance,mode=max,builder-id=https://github.com/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}
|
||||
|
||||
desktop-edge-test:
|
||||
runs-on: ubuntu-latest
|
||||
needs: bin-image
|
||||
steps:
|
||||
-
|
||||
name: Generate Token
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@v1
|
||||
with:
|
||||
app_id: ${{ vars.DOCKERDESKTOP_APP_ID }}
|
||||
private_key: ${{ secrets.DOCKERDESKTOP_APP_PRIVATEKEY }}
|
||||
repository: docker/${{ secrets.DOCKERDESKTOP_REPO }}
|
||||
-
|
||||
name: Trigger Docker Desktop e2e with edge version
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
github-token: ${{ steps.generate_token.outputs.token }}
|
||||
script: |
|
||||
await github.rest.actions.createWorkflowDispatch({
|
||||
owner: 'docker',
|
||||
repo: '${{ secrets.DOCKERDESKTOP_REPO }}',
|
||||
workflow_id: 'compose-edge-integration.yml',
|
||||
ref: 'main',
|
||||
inputs: {
|
||||
"image-tag": "${{ needs.bin-image.outputs.digest }}"
|
||||
}
|
||||
})
|
||||
|
||||
54
.github/workflows/scorecards.yml
vendored
Normal file
54
.github/workflows/scorecards.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Scorecards supply-chain security
|
||||
on:
|
||||
# Only the default branch is supported.
|
||||
branch_protection_rule:
|
||||
schedule:
|
||||
- cron: '44 9 * * 4'
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Used to receive a badge.
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # tag=v3.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # tag=v2.0.6
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
|
||||
# Publish the results for public repositories to enable scorecard badges. For more details, see
|
||||
# https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories, `publish_results` will automatically be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 # tag=v3.0.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@5f532563584d71fdef14ee64d17bafb34f751ce5 # tag=v1.0.26
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
bin/
|
||||
/.vscode/
|
||||
coverage.out
|
||||
covdatafiles/
|
||||
.DS_Store
|
||||
|
||||
@@ -31,12 +31,11 @@ linters-settings:
|
||||
- name: package-comments
|
||||
disabled: true
|
||||
depguard:
|
||||
list-type: denylist
|
||||
include-go-root: true
|
||||
packages:
|
||||
# The io/ioutil package has been deprecated.
|
||||
# https://go.dev/doc/go1.16#ioutil
|
||||
- io/ioutil
|
||||
rules:
|
||||
all:
|
||||
deny:
|
||||
- pkg: io/ioutil
|
||||
desc: 'io/ioutil package has been deprecated'
|
||||
gomodguard:
|
||||
blocked:
|
||||
versions:
|
||||
|
||||
43
Dockerfile
43
Dockerfile
@@ -15,26 +15,31 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
ARG GO_VERSION=1.19.3
|
||||
ARG XX_VERSION=1.1.2
|
||||
ARG GOLANGCI_LINT_VERSION=v1.49.0
|
||||
ARG GO_VERSION=1.21.0
|
||||
ARG XX_VERSION=1.2.1
|
||||
ARG GOLANGCI_LINT_VERSION=v1.53.2
|
||||
ARG ADDLICENSE_VERSION=v1.0.0
|
||||
|
||||
ARG BUILD_TAGS="e2e,kube"
|
||||
ARG BUILD_TAGS="e2e"
|
||||
ARG DOCS_FORMATS="md,yaml"
|
||||
ARG LICENSE_FILES=".*\(Dockerfile\|Makefile\|\.go\|\.hcl\|\.sh\)"
|
||||
|
||||
# xx is a helper for cross-compilation
|
||||
FROM --platform=${BUILDPLATFORM} tonistiigi/xx:${XX_VERSION} AS xx
|
||||
|
||||
# osxcross contains the MacOSX cross toolchain for xx
|
||||
FROM crazymax/osxcross:11.3-alpine AS osxcross
|
||||
|
||||
FROM golangci/golangci-lint:${GOLANGCI_LINT_VERSION}-alpine AS golangci-lint
|
||||
FROM ghcr.io/google/addlicense:${ADDLICENSE_VERSION} AS addlicense
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS base
|
||||
COPY --from=xx / /
|
||||
RUN apk add --no-cache \
|
||||
clang \
|
||||
docker \
|
||||
file \
|
||||
findutils \
|
||||
git \
|
||||
make \
|
||||
protoc \
|
||||
@@ -69,25 +74,24 @@ RUN --mount=type=bind,target=.,rw <<EOT
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM vendored AS modules-validate
|
||||
RUN apk add --no-cache bash
|
||||
RUN apk add --no-cache jq
|
||||
RUN --mount=type=bind,target=.,rw ./verify-go-modules.sh e2e
|
||||
|
||||
FROM build-base AS build
|
||||
ARG BUILD_TAGS
|
||||
ARG BUILD_FLAGS
|
||||
ARG TARGETPLATFORM
|
||||
RUN xx-go --wrap
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
make build GO_BUILDTAGS="$BUILD_TAGS" DESTDIR=/usr/bin && \
|
||||
xx-verify --static /usr/bin/docker-compose
|
||||
--mount=type=bind,from=osxcross,src=/osxsdk,target=/xx-sdk \
|
||||
xx-go --wrap && \
|
||||
if [ "$(xx-info os)" == "darwin" ]; then export CGO_ENABLED=1; fi && \
|
||||
make build GO_BUILDTAGS="$BUILD_TAGS" DESTDIR=/out && \
|
||||
xx-verify --static /out/docker-compose
|
||||
|
||||
FROM build-base AS lint
|
||||
ARG BUILD_TAGS
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
--mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \
|
||||
golangci-lint run --build-tags "$BUILD_TAGS" ./...
|
||||
|
||||
@@ -97,11 +101,13 @@ ARG BUILD_TAGS
|
||||
RUN --mount=type=bind,target=. \
|
||||
--mount=type=cache,target=/root/.cache \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
go test -tags "$BUILD_TAGS" -v -coverprofile=/tmp/coverage.txt -covermode=atomic $(go list $(TAGS) ./... | grep -vE 'e2e') && \
|
||||
go tool cover -func=/tmp/coverage.txt
|
||||
rm -rf /tmp/coverage && \
|
||||
mkdir -p /tmp/coverage && \
|
||||
go test -tags "$BUILD_TAGS" -v -cover -covermode=atomic $(go list $(TAGS) ./... | grep -vE 'e2e') -args -test.gocoverdir="/tmp/coverage" && \
|
||||
go tool covdata percent -i=/tmp/coverage
|
||||
|
||||
FROM scratch AS test-coverage
|
||||
COPY --from=test /tmp/coverage.txt /coverage.txt
|
||||
COPY --from=test --link /tmp/coverage /
|
||||
|
||||
FROM base AS license-set
|
||||
ARG LICENSE_FILES
|
||||
@@ -124,6 +130,7 @@ FROM base AS docsgen
|
||||
WORKDIR /src
|
||||
RUN --mount=target=. \
|
||||
--mount=target=/root/.cache,type=cache \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
go build -o /out/docsgen ./docs/yaml/main/generate.go
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} alpine AS docs-build
|
||||
@@ -159,12 +166,14 @@ RUN --mount=target=/context \
|
||||
EOT
|
||||
|
||||
FROM scratch AS binary-unix
|
||||
COPY --link --from=build /usr/bin/docker-compose /
|
||||
COPY --link --from=build /out/docker-compose /
|
||||
FROM binary-unix AS binary-darwin
|
||||
FROM binary-unix AS binary-linux
|
||||
FROM scratch AS binary-windows
|
||||
COPY --link --from=build /usr/bin/docker-compose /docker-compose.exe
|
||||
COPY --link --from=build /out/docker-compose /docker-compose.exe
|
||||
FROM binary-$TARGETOS AS binary
|
||||
# enable scanning for this stage
|
||||
ARG BUILDKIT_SBOM_SCAN_STAGE=true
|
||||
|
||||
FROM --platform=$BUILDPLATFORM alpine AS releaser
|
||||
WORKDIR /work
|
||||
|
||||
71
MAINTAINERS
71
MAINTAINERS
@@ -1,6 +1,6 @@
|
||||
# Docker maintainers file
|
||||
#
|
||||
# This file describes who runs the docker/compose-cli project and how.
|
||||
# This file describes who runs the docker/compose project and how.
|
||||
# This is a living document - if you see something out of date or missing, speak up!
|
||||
#
|
||||
# It is structured to be consumable by both humans and programs.
|
||||
@@ -22,13 +22,28 @@
|
||||
# subsystem maintainers accountable. If ownership is unclear, they are the de facto owners.
|
||||
|
||||
people = [
|
||||
"rumpl",
|
||||
"gtardif",
|
||||
"glours",
|
||||
"milas",
|
||||
"laurazard",
|
||||
"ndeloof",
|
||||
"chris-crone",
|
||||
"nicksieger",
|
||||
"StefanScherer",
|
||||
"ulyssessouza"
|
||||
]
|
||||
|
||||
[Org."Regular maintainers"]
|
||||
# The Regular maintainers are people who aren't Core maintainers but are around
|
||||
# to help reviewing and fixing bugs, just on a less regular basis than previously.
|
||||
# Most of them were previously Core maintainers of Compose.
|
||||
people = [
|
||||
"aiordache",
|
||||
"chris-crone",
|
||||
"gtardif",
|
||||
"maxcleme",
|
||||
"rumpl",
|
||||
"thaJeztah"
|
||||
]
|
||||
|
||||
[people]
|
||||
|
||||
# A reference list of all people associated with the project.
|
||||
@@ -37,16 +52,46 @@
|
||||
|
||||
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
|
||||
|
||||
[people.aiordache]
|
||||
Name = "Anca Iordache"
|
||||
Email = "anca.iordache@docker.com"
|
||||
GitHub = "aiordache "
|
||||
|
||||
[people.chris-crone]
|
||||
Name = "Christopher Crone"
|
||||
Email = "christopher.crone@docker.com"
|
||||
GitHub = "chris-crone"
|
||||
|
||||
[people.glours]
|
||||
Name = "Guillaume Lours"
|
||||
Email = "guillaume.lours@docker.com"
|
||||
GitHub = "glours"
|
||||
|
||||
[people.gtardif]
|
||||
Name = "Guillaume Tardif"
|
||||
Email = "guillaume.tardif@docker.com"
|
||||
GitHub = "gtardif"
|
||||
|
||||
[people.laurazard]
|
||||
Name = "Laura Brehm"
|
||||
Email = "laura.brehm@docker.com"
|
||||
GitHub = "laurazard"
|
||||
|
||||
[people.maxcleme]
|
||||
Name = "Maxime Clement"
|
||||
Email = "maxime.clement@docker.com"
|
||||
GitHub = "maxcleme"
|
||||
|
||||
[people.milas]
|
||||
Name = "Milas Bowman"
|
||||
Email = "milas.bowman@docker.com"
|
||||
GitHub = "milas"
|
||||
|
||||
[people.nicksieger]
|
||||
Name = "Nick Sieger"
|
||||
Email = "nick.sieger@docker.com"
|
||||
GitHub = "nicksieger"
|
||||
|
||||
[people.ndeloof]
|
||||
Name = "Nicolas Deloof"
|
||||
Email = "nicolas.deloof@docker.com"
|
||||
@@ -57,7 +102,17 @@
|
||||
Email = "djordje.lukic@docker.com"
|
||||
GitHub = "rumpl"
|
||||
|
||||
[people.ulyssessouza]
|
||||
Name = "Ulysses Souza"
|
||||
Email = "<ulysses.souza@docker.com"
|
||||
Github = "ulyssessouza"
|
||||
[people.thaJeztah]
|
||||
Name = "Sebastiaan van Stijn"
|
||||
Email = "sebastiaan.vanstijn@docker.com"
|
||||
GitHub = "thaJeztah "
|
||||
|
||||
[people.StefanScherer]
|
||||
Name = "Stefan Scherer"
|
||||
Email = "stefan.scherer@docker.com"
|
||||
GitHub = "StefanScherer"
|
||||
|
||||
[people.ulyssessouza]
|
||||
Name = "Ulysses Souza"
|
||||
Email = "<ulysses.souza@docker.com"
|
||||
Github = "ulyssessouza"
|
||||
|
||||
57
Makefile
57
Makefile
@@ -15,26 +15,22 @@
|
||||
PKG := github.com/docker/compose/v2
|
||||
VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags)
|
||||
|
||||
GO_LDFLAGS ?= -s -w -X ${PKG}/internal.Version=${VERSION}
|
||||
GO_BUILDTAGS ?= e2e,kube
|
||||
|
||||
GO_LDFLAGS ?= -w -X ${PKG}/internal.Version=${VERSION}
|
||||
GO_BUILDTAGS ?= e2e
|
||||
DRIVE_PREFIX?=
|
||||
ifeq ($(OS),Windows_NT)
|
||||
DETECTED_OS = Windows
|
||||
DRIVE_PREFIX=C:
|
||||
else
|
||||
DETECTED_OS = $(shell uname -s)
|
||||
endif
|
||||
ifeq ($(DETECTED_OS),Linux)
|
||||
MOBY_DOCKER=/usr/bin/docker
|
||||
endif
|
||||
ifeq ($(DETECTED_OS),Darwin)
|
||||
MOBY_DOCKER=/Applications/Docker.app/Contents/Resources/bin/docker
|
||||
endif
|
||||
|
||||
ifeq ($(DETECTED_OS),Windows)
|
||||
BINARY_EXT=.exe
|
||||
endif
|
||||
|
||||
TEST_COVERAGE_FLAGS = -race -coverprofile=coverage.out -covermode=atomic
|
||||
TEST_FLAGS?= -timeout 15m
|
||||
BUILD_FLAGS?=
|
||||
TEST_FLAGS?=
|
||||
E2E_TEST?=
|
||||
ifeq ($(E2E_TEST),)
|
||||
else
|
||||
@@ -42,33 +38,49 @@ else
|
||||
endif
|
||||
|
||||
BUILDX_CMD ?= docker buildx
|
||||
DESTDIR ?= ./bin/build
|
||||
|
||||
# DESTDIR overrides the output path for binaries and other artifacts
|
||||
# this is used by docker/docker-ce-packaging for the apt/rpm builds,
|
||||
# so it's important that the resulting binary ends up EXACTLY at the
|
||||
# path $DESTDIR/docker-compose when specified.
|
||||
#
|
||||
# See https://github.com/docker/docker-ce-packaging/blob/e43fbd37e48fde49d907b9195f23b13537521b94/rpm/SPECS/docker-compose-plugin.spec#L47
|
||||
#
|
||||
# By default, all artifacts go to subdirectories under ./bin/ in the
|
||||
# repo root, e.g. ./bin/build, ./bin/coverage, ./bin/release.
|
||||
DESTDIR ?=
|
||||
|
||||
all: build
|
||||
|
||||
.PHONY: build ## Build the compose cli-plugin
|
||||
build:
|
||||
CGO_ENABLED=0 GO111MODULE=on go build -trimpath -tags "$(GO_BUILDTAGS)" -ldflags "$(GO_LDFLAGS)" -o "$(DESTDIR)/docker-compose$(BINARY_EXT)" ./cmd
|
||||
GO111MODULE=on go build $(BUILD_FLAGS) -trimpath -tags "$(GO_BUILDTAGS)" -ldflags "$(GO_LDFLAGS)" -o "$(or $(DESTDIR),./bin/build)/docker-compose$(BINARY_EXT)" ./cmd
|
||||
|
||||
.PHONY: binary
|
||||
binary:
|
||||
$(BUILDX_CMD) bake binary
|
||||
|
||||
.PHONY: binary-with-coverage
|
||||
binary-with-coverage:
|
||||
$(BUILDX_CMD) bake binary-with-coverage
|
||||
|
||||
.PHONY: install
|
||||
install: binary
|
||||
mkdir -p ~/.docker/cli-plugins
|
||||
install bin/build/docker-compose ~/.docker/cli-plugins/docker-compose
|
||||
install $(or $(DESTDIR),./bin/build)/docker-compose ~/.docker/cli-plugins/docker-compose
|
||||
|
||||
.PHONY: e2e-compose
|
||||
e2e-compose: ## Run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test
|
||||
docker compose version
|
||||
go test $(TEST_FLAGS) $(TEST_COVERAGE_FLAGS) -count=1 ./pkg/e2e
|
||||
go test $(TEST_FLAGS) -count=1 ./pkg/e2e
|
||||
|
||||
.PHONY: e2e-compose-standalone
|
||||
e2e-compose-standalone: ## Run End to end local tests in standalone mode. Set E2E_TEST=TestName to run a single test
|
||||
docker-compose version
|
||||
go test $(TEST_FLAGS) -v -count=1 -parallel=1 --tags=standalone ./pkg/e2e
|
||||
|
||||
.PHONY: test-cucumber
|
||||
test-cucumber:
|
||||
go test $(TEST_FLAGS) -v -count=1 -parallel=1 ./e2e
|
||||
|
||||
.PHONY: build-and-e2e-compose
|
||||
build-and-e2e-compose: build e2e-compose ## Compile the compose cli-plugin and run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test
|
||||
|
||||
@@ -77,6 +89,7 @@ build-and-e2e-compose-standalone: build e2e-compose-standalone ## Compile the co
|
||||
|
||||
.PHONY: mocks
|
||||
mocks:
|
||||
mockgen --version >/dev/null 2>&1 || go install github.com/golang/mock/mockgen@v1.6.0
|
||||
mockgen -destination pkg/mocks/mock_docker_cli.go -package mocks github.com/docker/cli/cli/command Cli
|
||||
mockgen -destination pkg/mocks/mock_docker_api.go -package mocks github.com/docker/docker/client APIClient
|
||||
mockgen -destination pkg/mocks/mock_docker_compose_api.go -package mocks -source=./pkg/api/api.go Service
|
||||
@@ -108,8 +121,8 @@ docs: ## generate documentation
|
||||
$(eval $@_TMP_OUT := $(shell mktemp -d -t compose-output.XXXXXXXXXX))
|
||||
$(BUILDX_CMD) bake --set "*.output=type=local,dest=$($@_TMP_OUT)" docs-update
|
||||
rm -rf ./docs/internal
|
||||
cp -R "$($@_TMP_OUT)"/out/* ./docs/
|
||||
rm -rf "$($@_TMP_OUT)"/*
|
||||
cp -R "$(DRIVE_PREFIX)$($@_TMP_OUT)"/out/* ./docs/
|
||||
rm -rf "$(DRIVE_PREFIX)$($@_TMP_OUT)"/*
|
||||
|
||||
.PHONY: validate-docs
|
||||
validate-docs: ## validate the doc does not change
|
||||
@@ -131,11 +144,7 @@ go-mod-tidy: ## Run go mod tidy in a container and output resulting go.mod and g
|
||||
validate-go-mod: ## Validate go.mod and go.sum are up-to-date
|
||||
$(BUILDX_CMD) bake vendor-validate
|
||||
|
||||
.PHONY: validate-modules
|
||||
validate-modules: ## Validate root and e2e go.mod are synced
|
||||
$(BUILDX_CMD) bake modules-validate
|
||||
|
||||
validate: validate-go-mod validate-modules validate-headers validate-docs ## Validate sources
|
||||
validate: validate-go-mod validate-headers validate-docs ## Validate sources
|
||||
|
||||
pre-commit: validate check-dependencies lint build test e2e-compose
|
||||
|
||||
|
||||
28
README.md
28
README.md
@@ -1,11 +1,20 @@
|
||||
# Table of Contents
|
||||
- [Docker Compose v2](#docker-compose-v2)
|
||||
- [About update and backward compatibility](#about-update-and-backward-compatibility)
|
||||
- [Where to get Docker Compose](#where-to-get-docker-compose)
|
||||
+ [Windows and macOS](#windows-and-macos)
|
||||
+ [Linux](#linux)
|
||||
- [Quick Start](#quick-start)
|
||||
- [Contributing](#contributing)
|
||||
- [Legacy](#legacy)
|
||||
# Docker Compose v2
|
||||
|
||||
[](https://github.com/docker/compose/releases/latest)
|
||||
[](https://pkg.go.dev/github.com/docker/compose/v2)
|
||||
[](https://github.com/docker/compose/actions?query=workflow%3Aci)
|
||||
[](https://github.com/docker/compose/actions?query=workflow%3Aci)
|
||||
[](https://goreportcard.com/report/github.com/docker/compose/v2)
|
||||
[](https://codecov.io/gh/docker/compose)
|
||||
|
||||
[](https://codecov.io/gh/docker/compose)
|
||||
[](https://api.securityscorecards.dev/projects/github.com/docker/compose)
|
||||

|
||||
|
||||
Docker Compose is a tool for running multi-container applications on Docker
|
||||
@@ -15,12 +24,6 @@ your application are configured.
|
||||
Once you have a Compose file, you can create and start your application with a
|
||||
single command: `docker compose up`.
|
||||
|
||||
# About update and backward compatibility
|
||||
|
||||
Docker Compose V2 is a major version bump release of Docker Compose. It has been completely rewritten from scratch in Golang (V1 was in Python). The installation instructions for Compose V2 differ from V1. V2 is not a standalone binary anymore, and installation scripts will have to be adjusted. Some commands are different.
|
||||
|
||||
For a smooth transition from legacy docker-compose 1.xx, please consider installing [compose-switch](https://github.com/docker/compose-switch) to translate `docker-compose ...` commands into Compose V2's `docker compose .... `. Also check V2's `--compatibility` flag.
|
||||
|
||||
# Where to get Docker Compose
|
||||
|
||||
### Windows and macOS
|
||||
@@ -34,7 +37,7 @@ for Windows and macOS.
|
||||
You can download Docker Compose binaries from the
|
||||
[release page](https://github.com/docker/compose/releases) on this repository.
|
||||
|
||||
Rename the relevant binary for your OS to `docker-compose` and copy it to `$HOME/.docker/cli-plugins`
|
||||
Rename the relevant binary for your OS to `docker-compose` and copy it to `$HOME/.docker/cli-plugins`
|
||||
|
||||
Or copy it into one of these folders to install it system-wide:
|
||||
|
||||
@@ -77,3 +80,8 @@ Want to help develop Docker Compose? Check out our
|
||||
|
||||
If you find an issue, please report it on the
|
||||
[issue tracker](https://github.com/docker/compose/issues/new/choose).
|
||||
|
||||
Legacy
|
||||
-------------
|
||||
|
||||
The Python version of Compose is available under the `v1` [branch](https://github.com/docker/compose/tree/v1)
|
||||
131
cmd/cmdtrace/cmd_span.go
Normal file
131
cmd/cmdtrace/cmd_span.go
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Copyright 2023 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmdtrace
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
dockercli "github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
commands "github.com/docker/compose/v2/cmd/compose"
|
||||
"github.com/docker/compose/v2/internal/tracing"
|
||||
"github.com/spf13/cobra"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Setup should be called as part of the command's PersistentPreRunE
|
||||
// as soon as possible after initializing the dockerCli.
|
||||
//
|
||||
// It initializes the tracer for the CLI using both auto-detection
|
||||
// from the Docker context metadata as well as standard OTEL_ env
|
||||
// vars, creates a root span for the command, and wraps the actual
|
||||
// command invocation to ensure the span is properly finalized and
|
||||
// exported before exit.
|
||||
func Setup(cmd *cobra.Command, dockerCli command.Cli) error {
|
||||
tracingShutdown, err := tracing.InitTracing(dockerCli)
|
||||
if err != nil {
|
||||
return fmt.Errorf("initializing tracing: %w", err)
|
||||
}
|
||||
|
||||
ctx := cmd.Context()
|
||||
ctx, cmdSpan := tracing.Tracer.Start(
|
||||
ctx,
|
||||
"cli/"+strings.Join(commandName(cmd), "-"),
|
||||
)
|
||||
cmd.SetContext(ctx)
|
||||
wrapRunE(cmd, cmdSpan, tracingShutdown)
|
||||
return nil
|
||||
}
|
||||
|
||||
// wrapRunE injects a wrapper function around the command's actual RunE (or Run)
|
||||
// method. This is necessary to capture the command result for reporting as well
|
||||
// as flushing any spans before exit.
|
||||
//
|
||||
// Unfortunately, PersistentPostRun(E) can't be used for this purpose because it
|
||||
// only runs if RunE does _not_ return an error, but this should run unconditionally.
|
||||
func wrapRunE(c *cobra.Command, cmdSpan trace.Span, tracingShutdown tracing.ShutdownFunc) {
|
||||
origRunE := c.RunE
|
||||
if origRunE == nil {
|
||||
origRun := c.Run
|
||||
//nolint:unparam // wrapper function for RunE, always returns nil by design
|
||||
origRunE = func(cmd *cobra.Command, args []string) error {
|
||||
origRun(cmd, args)
|
||||
return nil
|
||||
}
|
||||
c.Run = nil
|
||||
}
|
||||
|
||||
c.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
cmdErr := origRunE(cmd, args)
|
||||
if cmdSpan != nil {
|
||||
if cmdErr != nil && !errors.Is(cmdErr, context.Canceled) {
|
||||
// default exit code is 1 if a more descriptive error
|
||||
// wasn't returned
|
||||
exitCode := 1
|
||||
var statusErr dockercli.StatusError
|
||||
if errors.As(cmdErr, &statusErr) {
|
||||
exitCode = statusErr.StatusCode
|
||||
}
|
||||
cmdSpan.SetStatus(codes.Error, "CLI command returned error")
|
||||
cmdSpan.RecordError(cmdErr, trace.WithAttributes(
|
||||
attribute.Int("exit_code", exitCode),
|
||||
))
|
||||
|
||||
} else {
|
||||
cmdSpan.SetStatus(codes.Ok, "")
|
||||
}
|
||||
cmdSpan.End()
|
||||
}
|
||||
if tracingShutdown != nil {
|
||||
// use background for root context because the cmd's context might have
|
||||
// been canceled already
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
// TODO(milas): add an env var to enable logging from the
|
||||
// OTel components for debugging purposes
|
||||
_ = tracingShutdown(ctx)
|
||||
}
|
||||
return cmdErr
|
||||
}
|
||||
}
|
||||
|
||||
// commandName returns the path components for a given command.
|
||||
//
|
||||
// The root Compose command and anything before (i.e. "docker")
|
||||
// are not included.
|
||||
//
|
||||
// For example:
|
||||
// - docker compose alpha watch -> [alpha, watch]
|
||||
// - docker-compose up -> [up]
|
||||
func commandName(cmd *cobra.Command) []string {
|
||||
var name []string
|
||||
for c := cmd; c != nil; c = c.Parent() {
|
||||
if c.Name() == commands.PluginName {
|
||||
break
|
||||
}
|
||||
name = append(name, c.Name())
|
||||
}
|
||||
sort.Sort(sort.Reverse(sort.StringSlice(name)))
|
||||
return name
|
||||
}
|
||||
@@ -62,10 +62,6 @@ func Convert(args []string) []string {
|
||||
continue
|
||||
}
|
||||
if len(arg) > 0 && arg[0] != '-' {
|
||||
// not a top-level flag anymore, keep the rest of the command unmodified
|
||||
if arg == compose.PluginName {
|
||||
i++
|
||||
}
|
||||
command = append(command, args[i:]...)
|
||||
break
|
||||
}
|
||||
|
||||
@@ -83,6 +83,11 @@ func Test_convert(t *testing.T) {
|
||||
args: []string{"--project-directory", "", "ps"},
|
||||
want: []string{"compose", "--project-directory", "", "ps"},
|
||||
},
|
||||
{
|
||||
name: "compose as project name",
|
||||
args: []string{"--project-name", "compose", "down", "--remove-orphans"},
|
||||
want: []string{"compose", "--project-name", "compose", "down", "--remove-orphans"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
38
cmd/compose/alpha.go
Normal file
38
cmd/compose/alpha.go
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// alphaCommand groups all experimental subcommands
|
||||
func alphaCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Short: "Experimental commands",
|
||||
Use: "alpha [COMMAND]",
|
||||
Hidden: true,
|
||||
Annotations: map[string]string{
|
||||
"experimentalCLI": "true",
|
||||
},
|
||||
}
|
||||
cmd.AddCommand(
|
||||
watchCommand(p, backend),
|
||||
vizCommand(p, backend),
|
||||
publishCommand(p, backend),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
@@ -26,23 +26,24 @@ import (
|
||||
"github.com/compose-spec/compose-go/loader"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
buildx "github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/compose/v2/pkg/progress"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
cliopts "github.com/docker/cli/opts"
|
||||
ui "github.com/docker/compose/v2/pkg/progress"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
)
|
||||
|
||||
type buildOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
composeOptions
|
||||
quiet bool
|
||||
pull bool
|
||||
progress string
|
||||
args []string
|
||||
noCache bool
|
||||
memory string
|
||||
ssh string
|
||||
quiet bool
|
||||
pull bool
|
||||
push bool
|
||||
args []string
|
||||
noCache bool
|
||||
memory cliopts.MemBytes
|
||||
ssh string
|
||||
builder string
|
||||
}
|
||||
|
||||
func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions, error) {
|
||||
@@ -54,65 +55,59 @@ func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions,
|
||||
return api.BuildOptions{}, err
|
||||
}
|
||||
}
|
||||
builderName := opts.builder
|
||||
if builderName == "" {
|
||||
builderName = os.Getenv("BUILDX_BUILDER")
|
||||
}
|
||||
|
||||
return api.BuildOptions{
|
||||
Pull: opts.pull,
|
||||
Progress: opts.progress,
|
||||
Push: opts.push,
|
||||
Progress: ui.Mode,
|
||||
Args: types.NewMappingWithEquals(opts.args),
|
||||
NoCache: opts.noCache,
|
||||
Quiet: opts.quiet,
|
||||
Services: services,
|
||||
SSHs: SSHKeys,
|
||||
Builder: builderName,
|
||||
}, nil
|
||||
}
|
||||
|
||||
var printerModes = []string{
|
||||
buildx.PrinterModeAuto,
|
||||
buildx.PrinterModeTty,
|
||||
buildx.PrinterModePlain,
|
||||
buildx.PrinterModeQuiet,
|
||||
}
|
||||
|
||||
func buildCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func buildCommand(p *ProjectOptions, progress *string, backend api.Service) *cobra.Command {
|
||||
opts := buildOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "build [OPTIONS] [SERVICE...]",
|
||||
Short: "Build or rebuild services",
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.memory != "" {
|
||||
fmt.Println("WARNING --memory is ignored as not supported in buildkit.")
|
||||
}
|
||||
if opts.quiet {
|
||||
opts.progress = buildx.PrinterModeQuiet
|
||||
ui.Mode = ui.ModeQuiet
|
||||
devnull, err := os.Open(os.DevNull)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
os.Stdout = devnull
|
||||
}
|
||||
if !utils.StringContains(printerModes, opts.progress) {
|
||||
return fmt.Errorf("unsupported --progress value %q", opts.progress)
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
RunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
if cmd.Flags().Changed("ssh") && opts.ssh == "" {
|
||||
opts.ssh = "default"
|
||||
}
|
||||
if progress.Mode == progress.ModePlain && !cmd.Flags().Changed("progress") {
|
||||
opts.progress = buildx.PrinterModePlain
|
||||
if cmd.Flags().Changed("progress") && opts.ssh == "" {
|
||||
fmt.Fprint(os.Stderr, "--progress is a global compose flag, better use `docker compose --progress xx build ...")
|
||||
}
|
||||
return runBuild(ctx, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
cmd.Flags().BoolVar(&opts.push, "push", false, "Push service images.")
|
||||
cmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false, "Don't print anything to STDOUT")
|
||||
cmd.Flags().BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image.")
|
||||
cmd.Flags().StringVar(&opts.progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of progress output (%s)`, strings.Join(printerModes, ", ")))
|
||||
cmd.Flags().StringArrayVar(&opts.args, "build-arg", []string{}, "Set build-time variables for services.")
|
||||
cmd.Flags().StringVar(&opts.ssh, "ssh", "", "Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent)")
|
||||
cmd.Flags().StringVar(&opts.builder, "builder", "", "Set builder to use.")
|
||||
cmd.Flags().Bool("parallel", true, "Build images in parallel. DEPRECATED")
|
||||
cmd.Flags().MarkHidden("parallel") //nolint:errcheck
|
||||
cmd.Flags().Bool("compress", true, "Compress the build context using gzip. DEPRECATED")
|
||||
@@ -122,14 +117,15 @@ func buildCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
cmd.Flags().BoolVar(&opts.noCache, "no-cache", false, "Do not use cache when building the image")
|
||||
cmd.Flags().Bool("no-rm", false, "Do not remove intermediate containers after a successful build. DEPRECATED")
|
||||
cmd.Flags().MarkHidden("no-rm") //nolint:errcheck
|
||||
cmd.Flags().StringVarP(&opts.memory, "memory", "m", "", "Set memory limit for the build container. Not supported on buildkit yet.")
|
||||
cmd.Flags().MarkHidden("memory") //nolint:errcheck
|
||||
cmd.Flags().VarP(&opts.memory, "memory", "m", "Set memory limit for the build container. Not supported by BuildKit.")
|
||||
cmd.Flags().StringVar(progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of ui output (%s)`, strings.Join(printerModes, ", ")))
|
||||
cmd.Flags().MarkHidden("progress") //nolint:errcheck
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runBuild(ctx context.Context, backend api.Service, opts buildOptions, services []string) error {
|
||||
project, err := opts.toProject(services, cli.WithResolvedPaths(true))
|
||||
project, err := opts.ToProject(services, cli.WithResolvedPaths(true))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -138,5 +134,7 @@ func runBuild(ctx context.Context, backend api.Service, opts buildOptions, servi
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
apiBuildOptions.Memory = int64(opts.memory)
|
||||
return backend.Build(ctx, project, apiBuildOptions)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
@@ -32,9 +33,9 @@ func noCompletion() validArgsFn {
|
||||
}
|
||||
}
|
||||
|
||||
func completeServiceNames(p *projectOptions) validArgsFn {
|
||||
func completeServiceNames(p *ProjectOptions) validArgsFn {
|
||||
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
project, err := p.toProject(nil)
|
||||
project, err := p.ToProject(nil)
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
@@ -65,3 +66,23 @@ func completeProjectNames(backend api.Service) func(cmd *cobra.Command, args []s
|
||||
return values, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
}
|
||||
|
||||
func completeProfileNames(p *ProjectOptions) validArgsFn {
|
||||
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
project, err := p.ToProject(nil)
|
||||
if err != nil {
|
||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
|
||||
allProfileNames := project.AllServices().GetProfiles()
|
||||
sort.Strings(allProfileNames)
|
||||
|
||||
var values []string
|
||||
for _, profileName := range allProfileNames {
|
||||
if strings.HasPrefix(profileName, toComplete) {
|
||||
values = append(values, profileName)
|
||||
}
|
||||
}
|
||||
return values, cobra.ShellCompDirectiveNoFileComp
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,16 +22,20 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/compose-spec/compose-go/dotenv"
|
||||
buildx "github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/cli/cli/command"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
composegoutils "github.com/compose-spec/compose-go/utils"
|
||||
"github.com/docker/buildx/util/logutil"
|
||||
dockercli "github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/morikuni/aec"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -41,10 +45,23 @@ import (
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
"github.com/docker/compose/v2/pkg/progress"
|
||||
ui "github.com/docker/compose/v2/pkg/progress"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
// ComposeParallelLimit set the limit running concurrent operation on docker engine
|
||||
ComposeParallelLimit = "COMPOSE_PARALLEL_LIMIT"
|
||||
// ComposeProjectName define the project name to be used, instead of guessing from parent directory
|
||||
ComposeProjectName = "COMPOSE_PROJECT_NAME"
|
||||
// ComposeCompatibility try to mimic compose v1 as much as possible
|
||||
ComposeCompatibility = "COMPOSE_COMPATIBILITY"
|
||||
// ComposeRemoveOrphans remove “orphaned" containers, i.e. containers tagged for current project but not declared as service
|
||||
ComposeRemoveOrphans = "COMPOSE_REMOVE_ORPHANS"
|
||||
// ComposeIgnoreOrphans ignore "orphaned" containers
|
||||
ComposeIgnoreOrphans = "COMPOSE_IGNORE_ORPHANS"
|
||||
)
|
||||
|
||||
// Command defines a compose CLI command as a func with args
|
||||
type Command func(context.Context, []string) error
|
||||
|
||||
@@ -91,13 +108,13 @@ func Adapt(fn Command) func(cmd *cobra.Command, args []string) error {
|
||||
})
|
||||
}
|
||||
|
||||
type projectOptions struct {
|
||||
type ProjectOptions struct {
|
||||
ProjectName string
|
||||
Profiles []string
|
||||
ConfigPaths []string
|
||||
WorkDir string
|
||||
ProjectDir string
|
||||
EnvFile string
|
||||
EnvFiles []string
|
||||
Compatibility bool
|
||||
}
|
||||
|
||||
@@ -108,16 +125,16 @@ type ProjectFunc func(ctx context.Context, project *types.Project) error
|
||||
type ProjectServicesFunc func(ctx context.Context, project *types.Project, services []string) error
|
||||
|
||||
// WithProject creates a cobra run command from a ProjectFunc based on configured project options and selected services
|
||||
func (o *projectOptions) WithProject(fn ProjectFunc) func(cmd *cobra.Command, args []string) error {
|
||||
func (o *ProjectOptions) WithProject(fn ProjectFunc) func(cmd *cobra.Command, args []string) error {
|
||||
return o.WithServices(func(ctx context.Context, project *types.Project, services []string) error {
|
||||
return fn(ctx, project)
|
||||
})
|
||||
}
|
||||
|
||||
// WithServices creates a cobra run command from a ProjectFunc based on configured project options and selected services
|
||||
func (o *projectOptions) WithServices(fn ProjectServicesFunc) func(cmd *cobra.Command, args []string) error {
|
||||
func (o *ProjectOptions) WithServices(fn ProjectServicesFunc) func(cmd *cobra.Command, args []string) error {
|
||||
return Adapt(func(ctx context.Context, args []string) error {
|
||||
project, err := o.toProject(args, cli.WithResolvedPaths(true))
|
||||
project, err := o.ToProject(args, cli.WithResolvedPaths(true), cli.WithDiscardEnvFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -126,24 +143,24 @@ func (o *projectOptions) WithServices(fn ProjectServicesFunc) func(cmd *cobra.Co
|
||||
})
|
||||
}
|
||||
|
||||
func (o *projectOptions) addProjectFlags(f *pflag.FlagSet) {
|
||||
func (o *ProjectOptions) addProjectFlags(f *pflag.FlagSet) {
|
||||
f.StringArrayVar(&o.Profiles, "profile", []string{}, "Specify a profile to enable")
|
||||
f.StringVarP(&o.ProjectName, "project-name", "p", "", "Project name")
|
||||
f.StringArrayVarP(&o.ConfigPaths, "file", "f", []string{}, "Compose configuration files")
|
||||
f.StringVar(&o.EnvFile, "env-file", "", "Specify an alternate environment file.")
|
||||
f.StringArrayVar(&o.EnvFiles, "env-file", nil, "Specify an alternate environment file.")
|
||||
f.StringVar(&o.ProjectDir, "project-directory", "", "Specify an alternate working directory\n(default: the path of the, first specified, Compose file)")
|
||||
f.StringVar(&o.WorkDir, "workdir", "", "DEPRECATED! USE --project-directory INSTEAD.\nSpecify an alternate working directory\n(default: the path of the, first specified, Compose file)")
|
||||
f.BoolVar(&o.Compatibility, "compatibility", false, "Run compose in backward compatibility mode")
|
||||
_ = f.MarkHidden("workdir")
|
||||
}
|
||||
|
||||
func (o *projectOptions) projectOrName(services ...string) (*types.Project, string, error) {
|
||||
func (o *ProjectOptions) projectOrName(services ...string) (*types.Project, string, error) {
|
||||
name := o.ProjectName
|
||||
var project *types.Project
|
||||
if o.ProjectName == "" {
|
||||
p, err := o.toProject(services)
|
||||
if len(o.ConfigPaths) > 0 || o.ProjectName == "" {
|
||||
p, err := o.ToProject(services, cli.WithDiscardEnvFile)
|
||||
if err != nil {
|
||||
envProjectName := os.Getenv("COMPOSE_PROJECT_NAME")
|
||||
envProjectName := os.Getenv(ComposeProjectName)
|
||||
if envProjectName != "" {
|
||||
return nil, envProjectName, nil
|
||||
}
|
||||
@@ -155,30 +172,30 @@ func (o *projectOptions) projectOrName(services ...string) (*types.Project, stri
|
||||
return project, name, nil
|
||||
}
|
||||
|
||||
func (o *projectOptions) toProjectName() (string, error) {
|
||||
func (o *ProjectOptions) toProjectName() (string, error) {
|
||||
if o.ProjectName != "" {
|
||||
return o.ProjectName, nil
|
||||
}
|
||||
|
||||
envProjectName := os.Getenv("COMPOSE_PROJECT_NAME")
|
||||
envProjectName := os.Getenv(ComposeProjectName)
|
||||
if envProjectName != "" {
|
||||
return envProjectName, nil
|
||||
}
|
||||
|
||||
project, err := o.toProject(nil)
|
||||
project, err := o.ToProject(nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return project.Name, nil
|
||||
}
|
||||
|
||||
func (o *projectOptions) toProject(services []string, po ...cli.ProjectOptionsFn) (*types.Project, error) {
|
||||
func (o *ProjectOptions) ToProject(services []string, po ...cli.ProjectOptionsFn) (*types.Project, error) {
|
||||
options, err := o.toProjectOptions(po...)
|
||||
if err != nil {
|
||||
return nil, compose.WrapComposeError(err)
|
||||
}
|
||||
|
||||
if o.Compatibility || utils.StringToBool(options.Environment["COMPOSE_COMPATIBILITY"]) {
|
||||
if o.Compatibility || utils.StringToBool(options.Environment[ComposeCompatibility]) {
|
||||
api.Separator = "_"
|
||||
}
|
||||
|
||||
@@ -187,13 +204,15 @@ func (o *projectOptions) toProject(services []string, po ...cli.ProjectOptionsFn
|
||||
return nil, compose.WrapComposeError(err)
|
||||
}
|
||||
|
||||
ef := o.EnvFile
|
||||
if ef != "" && !filepath.IsAbs(ef) {
|
||||
ef, err = filepath.Abs(ef)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if project.Name == "" {
|
||||
return nil, errors.New("project name can't be empty. Use `--project-name` to set a valid name")
|
||||
}
|
||||
|
||||
err = project.EnableServices(services...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i, s := range project.Services {
|
||||
s.CustomLabels = map[string]string{
|
||||
api.ProjectLabel: project.Name,
|
||||
@@ -203,41 +222,28 @@ func (o *projectOptions) toProject(services []string, po ...cli.ProjectOptionsFn
|
||||
api.ConfigFilesLabel: strings.Join(project.ComposeFiles, ","),
|
||||
api.OneoffLabel: "False", // default, will be overridden by `run` command
|
||||
}
|
||||
if ef != "" {
|
||||
s.CustomLabels[api.EnvironmentFileLabel] = ef
|
||||
if len(o.EnvFiles) != 0 {
|
||||
s.CustomLabels[api.EnvironmentFileLabel] = strings.Join(o.EnvFiles, ",")
|
||||
}
|
||||
project.Services[i] = s
|
||||
}
|
||||
|
||||
if profiles, ok := options.Environment["COMPOSE_PROFILES"]; ok && len(o.Profiles) == 0 {
|
||||
o.Profiles = append(o.Profiles, strings.Split(profiles, ",")...)
|
||||
}
|
||||
|
||||
if len(services) > 0 {
|
||||
s, err := project.GetServices(services...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o.Profiles = append(o.Profiles, s.GetProfiles()...)
|
||||
}
|
||||
|
||||
project.ApplyProfiles(o.Profiles)
|
||||
|
||||
project.WithoutUnnecessaryResources()
|
||||
|
||||
err = project.ForServices(services)
|
||||
return project, err
|
||||
}
|
||||
|
||||
func (o *projectOptions) toProjectOptions(po ...cli.ProjectOptionsFn) (*cli.ProjectOptions, error) {
|
||||
func (o *ProjectOptions) toProjectOptions(po ...cli.ProjectOptionsFn) (*cli.ProjectOptions, error) {
|
||||
return cli.NewProjectOptions(o.ConfigPaths,
|
||||
append(po,
|
||||
cli.WithWorkingDirectory(o.ProjectDir),
|
||||
cli.WithOsEnv,
|
||||
cli.WithEnvFile(o.EnvFile),
|
||||
cli.WithEnvFiles(o.EnvFiles...),
|
||||
cli.WithDotEnv,
|
||||
cli.WithConfigFileEnv,
|
||||
cli.WithDefaultConfigPath,
|
||||
cli.WithProfiles(o.Profiles),
|
||||
cli.WithName(o.ProjectName))...)
|
||||
}
|
||||
|
||||
@@ -250,7 +256,7 @@ func RunningAsStandalone() bool {
|
||||
}
|
||||
|
||||
// RootCommand returns the compose command with its child commands
|
||||
func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //nolint:gocyclo
|
||||
// filter out useless commandConn.CloseWrite warning message that can occur
|
||||
// when using a remote context that is unreachable: "commandConn.CloseWrite: commandconn: failed to wait: signal: killed"
|
||||
// https://github.com/docker/cli/blob/e1f24d3c93df6752d3c27c8d61d18260f141310c/cli/connhelper/commandconn/commandconn.go#L203-L215
|
||||
@@ -261,15 +267,19 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
"commandConn.CloseRead:",
|
||||
))
|
||||
|
||||
opts := projectOptions{}
|
||||
opts := ProjectOptions{}
|
||||
var (
|
||||
ansi string
|
||||
noAnsi bool
|
||||
verbose bool
|
||||
version bool
|
||||
ansi string
|
||||
noAnsi bool
|
||||
verbose bool
|
||||
version bool
|
||||
parallel int
|
||||
dryRun bool
|
||||
progress string
|
||||
)
|
||||
c := &cobra.Command{
|
||||
Short: "Docker Compose",
|
||||
Long: "Define and run multi-container applications with Docker.",
|
||||
Use: PluginName,
|
||||
TraverseChildren: true,
|
||||
// By default (no Run/RunE in parent c) for typos in subcommands, cobra displays the help of parent c but exit(0) !
|
||||
@@ -278,7 +288,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
return cmd.Help()
|
||||
}
|
||||
if version {
|
||||
return versionCommand().Execute()
|
||||
return versionCommand(streams).Execute()
|
||||
}
|
||||
_ = cmd.Help()
|
||||
return dockercli.StatusError{
|
||||
@@ -311,13 +321,44 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
if verbose {
|
||||
logrus.SetLevel(logrus.TraceLevel)
|
||||
}
|
||||
formatter.SetANSIMode(ansi)
|
||||
|
||||
if v, ok := os.LookupEnv("COMPOSE_ANSI"); ok && !cmd.Flags().Changed("ansi") {
|
||||
ansi = v
|
||||
}
|
||||
|
||||
formatter.SetANSIMode(streams, ansi)
|
||||
|
||||
if noColor, ok := os.LookupEnv("NO_COLOR"); ok && noColor != "" {
|
||||
ui.NoColor()
|
||||
formatter.SetANSIMode(streams, formatter.Never)
|
||||
}
|
||||
|
||||
switch ansi {
|
||||
case "never":
|
||||
progress.Mode = progress.ModePlain
|
||||
case "tty":
|
||||
progress.Mode = progress.ModeTTY
|
||||
ui.Mode = ui.ModePlain
|
||||
case "always":
|
||||
ui.Mode = ui.ModeTTY
|
||||
}
|
||||
|
||||
switch progress {
|
||||
case ui.ModeAuto:
|
||||
ui.Mode = ui.ModeAuto
|
||||
case ui.ModeTTY:
|
||||
if ansi == "never" {
|
||||
return fmt.Errorf("can't use --progress tty while ANSI support is disabled")
|
||||
}
|
||||
ui.Mode = ui.ModeTTY
|
||||
case ui.ModePlain:
|
||||
if ansi == "always" {
|
||||
return fmt.Errorf("can't use --progress plain while ANSI support is forced")
|
||||
}
|
||||
ui.Mode = ui.ModePlain
|
||||
case ui.ModeQuiet, "none":
|
||||
ui.Mode = ui.ModeQuiet
|
||||
default:
|
||||
return fmt.Errorf("unsupported --progress value %q", progress)
|
||||
}
|
||||
|
||||
if opts.WorkDir != "" {
|
||||
if opts.ProjectDir != "" {
|
||||
return errors.New(`cannot specify DEPRECATED "--workdir" and "--project-directory". Please use only "--project-directory" instead`)
|
||||
@@ -325,52 +366,105 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
opts.ProjectDir = opts.WorkDir
|
||||
fmt.Fprint(os.Stderr, aec.Apply("option '--workdir' is DEPRECATED at root level! Please use '--project-directory' instead.\n", aec.RedF))
|
||||
}
|
||||
for i, file := range opts.EnvFiles {
|
||||
if !filepath.IsAbs(file) {
|
||||
file, err = filepath.Abs(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts.EnvFiles[i] = file
|
||||
}
|
||||
}
|
||||
|
||||
composeCmd := cmd
|
||||
for {
|
||||
if composeCmd.Name() == PluginName {
|
||||
break
|
||||
}
|
||||
if !composeCmd.HasParent() {
|
||||
return fmt.Errorf("error parsing command line, expected %q", PluginName)
|
||||
}
|
||||
composeCmd = composeCmd.Parent()
|
||||
}
|
||||
|
||||
if v, ok := os.LookupEnv(ComposeParallelLimit); ok && !composeCmd.Flags().Changed("parallel") {
|
||||
i, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s must be an integer (found: %q)", ComposeParallelLimit, v)
|
||||
}
|
||||
parallel = i
|
||||
}
|
||||
if parallel > 0 {
|
||||
backend.MaxConcurrency(parallel)
|
||||
}
|
||||
ctx, err := backend.DryRunMode(cmd.Context(), dryRun)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd.SetContext(ctx)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
c.AddCommand(
|
||||
upCommand(&opts, backend),
|
||||
upCommand(&opts, streams, backend),
|
||||
downCommand(&opts, backend),
|
||||
startCommand(&opts, backend),
|
||||
restartCommand(&opts, backend),
|
||||
stopCommand(&opts, backend),
|
||||
psCommand(&opts, backend),
|
||||
listCommand(backend),
|
||||
logsCommand(&opts, backend),
|
||||
convertCommand(&opts, backend),
|
||||
psCommand(&opts, streams, backend),
|
||||
listCommand(streams, backend),
|
||||
logsCommand(&opts, streams, backend),
|
||||
configCommand(&opts, streams, backend),
|
||||
killCommand(&opts, backend),
|
||||
runCommand(&opts, dockerCli, backend),
|
||||
runCommand(&opts, streams, backend),
|
||||
removeCommand(&opts, backend),
|
||||
execCommand(&opts, dockerCli, backend),
|
||||
execCommand(&opts, streams, backend),
|
||||
pauseCommand(&opts, backend),
|
||||
unpauseCommand(&opts, backend),
|
||||
topCommand(&opts, backend),
|
||||
eventsCommand(&opts, backend),
|
||||
portCommand(&opts, backend),
|
||||
imagesCommand(&opts, backend),
|
||||
versionCommand(),
|
||||
buildCommand(&opts, backend),
|
||||
topCommand(&opts, streams, backend),
|
||||
eventsCommand(&opts, streams, backend),
|
||||
portCommand(&opts, streams, backend),
|
||||
imagesCommand(&opts, streams, backend),
|
||||
versionCommand(streams),
|
||||
buildCommand(&opts, &progress, backend),
|
||||
pushCommand(&opts, backend),
|
||||
pullCommand(&opts, backend),
|
||||
createCommand(&opts, backend),
|
||||
copyCommand(&opts, backend),
|
||||
waitCommand(&opts, backend),
|
||||
alphaCommand(&opts, backend),
|
||||
)
|
||||
|
||||
c.Flags().SetInterspersed(false)
|
||||
opts.addProjectFlags(c.Flags())
|
||||
c.RegisterFlagCompletionFunc( //nolint:errcheck
|
||||
"project-name",
|
||||
completeProjectNames(backend),
|
||||
)
|
||||
c.RegisterFlagCompletionFunc( //nolint:errcheck
|
||||
"project-directory",
|
||||
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return []string{}, cobra.ShellCompDirectiveFilterDirs
|
||||
},
|
||||
)
|
||||
c.RegisterFlagCompletionFunc( //nolint:errcheck
|
||||
"file",
|
||||
func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return []string{"yaml", "yml"}, cobra.ShellCompDirectiveFilterFileExt
|
||||
},
|
||||
)
|
||||
c.RegisterFlagCompletionFunc( //nolint:errcheck
|
||||
"profile",
|
||||
completeProfileNames(&opts),
|
||||
)
|
||||
|
||||
c.Flags().StringVar(&progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of progress output (%s)`, strings.Join(printerModes, ", ")))
|
||||
|
||||
c.Flags().StringVar(&ansi, "ansi", "auto", `Control when to print ANSI control characters ("never"|"always"|"auto")`)
|
||||
c.Flags().IntVar(¶llel, "parallel", -1, `Control max parallelism, -1 for unlimited`)
|
||||
c.Flags().BoolVarP(&version, "version", "v", false, "Show the Docker Compose version information")
|
||||
c.PersistentFlags().BoolVar(&dryRun, "dry-run", false, "Execute command in dry run mode")
|
||||
c.Flags().MarkHidden("version") //nolint:errcheck
|
||||
c.Flags().BoolVar(&noAnsi, "no-ansi", false, `Do not print ANSI control characters (DEPRECATED)`)
|
||||
c.Flags().MarkHidden("no-ansi") //nolint:errcheck
|
||||
@@ -379,7 +473,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
return c
|
||||
}
|
||||
|
||||
func setEnvWithDotEnv(prjOpts *projectOptions) error {
|
||||
func setEnvWithDotEnv(prjOpts *ProjectOptions) error {
|
||||
options, err := prjOpts.toProjectOptions()
|
||||
if err != nil {
|
||||
return compose.WrapComposeError(err)
|
||||
@@ -389,7 +483,7 @@ func setEnvWithDotEnv(prjOpts *projectOptions) error {
|
||||
return err
|
||||
}
|
||||
|
||||
envFromFile, err := cli.GetEnvFromFile(composegoutils.GetAsEqualsMap(os.Environ()), workingDir, options.EnvFile)
|
||||
envFromFile, err := dotenv.GetEnvFromFile(composegoutils.GetAsEqualsMap(os.Environ()), workingDir, options.EnvFiles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -402,3 +496,10 @@ func setEnvWithDotEnv(prjOpts *projectOptions) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var printerModes = []string{
|
||||
ui.ModeAuto,
|
||||
ui.ModeTTY,
|
||||
ui.ModePlain,
|
||||
ui.ModeQuiet,
|
||||
}
|
||||
|
||||
@@ -31,8 +31,10 @@ func TestFilterServices(t *testing.T) {
|
||||
Links: []string{"bar"},
|
||||
},
|
||||
{
|
||||
Name: "bar",
|
||||
NetworkMode: types.NetworkModeServicePrefix + "zot",
|
||||
Name: "bar",
|
||||
DependsOn: map[string]types.ServiceDependency{
|
||||
"zot": {},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "zot",
|
||||
|
||||
@@ -17,11 +17,9 @@
|
||||
package compose
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
@@ -34,14 +32,15 @@ import (
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
)
|
||||
|
||||
type convertOptions struct {
|
||||
*projectOptions
|
||||
type configOptions struct {
|
||||
*ProjectOptions
|
||||
Format string
|
||||
Output string
|
||||
quiet bool
|
||||
resolveImageDigests bool
|
||||
noInterpolate bool
|
||||
noNormalize bool
|
||||
noResolvePath bool
|
||||
services bool
|
||||
volumes bool
|
||||
profiles bool
|
||||
@@ -50,14 +49,24 @@ type convertOptions struct {
|
||||
noConsistency bool
|
||||
}
|
||||
|
||||
func convertCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
opts := convertOptions{
|
||||
projectOptions: p,
|
||||
func (o *configOptions) ToProject(services []string) (*types.Project, error) {
|
||||
return o.ProjectOptions.ToProject(services,
|
||||
cli.WithInterpolation(!o.noInterpolate),
|
||||
cli.WithResolvedPaths(!o.noResolvePath),
|
||||
cli.WithNormalization(!o.noNormalize),
|
||||
cli.WithConsistency(!o.noConsistency),
|
||||
cli.WithProfiles(o.Profiles),
|
||||
cli.WithDiscardEnvFile)
|
||||
}
|
||||
|
||||
func configCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
opts := configOptions{
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Aliases: []string{"config"},
|
||||
Use: "convert [OPTIONS] [SERVICE...]",
|
||||
Short: "Converts the compose file to platform's canonical format",
|
||||
Aliases: []string{"convert"}, // for backward compatibility with Cloud integrations
|
||||
Use: "config [OPTIONS] [SERVICE...]",
|
||||
Short: "Parse, resolve and render compose file in canonical format",
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.quiet {
|
||||
devnull, err := os.Open(os.DevNull)
|
||||
@@ -73,22 +82,22 @@ func convertCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}),
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
if opts.services {
|
||||
return runServices(opts)
|
||||
return runServices(streams, opts)
|
||||
}
|
||||
if opts.volumes {
|
||||
return runVolumes(opts)
|
||||
return runVolumes(streams, opts)
|
||||
}
|
||||
if opts.hash != "" {
|
||||
return runHash(opts)
|
||||
return runHash(streams, opts)
|
||||
}
|
||||
if opts.profiles {
|
||||
return runProfiles(opts, args)
|
||||
return runProfiles(streams, opts, args)
|
||||
}
|
||||
if opts.images {
|
||||
return runConfigImages(opts, args)
|
||||
return runConfigImages(streams, opts, args)
|
||||
}
|
||||
|
||||
return runConvert(ctx, backend, opts, args)
|
||||
return runConfig(ctx, streams, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
@@ -98,6 +107,7 @@ func convertCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only validate the configuration, don't print anything.")
|
||||
flags.BoolVar(&opts.noInterpolate, "no-interpolate", false, "Don't interpolate environment variables.")
|
||||
flags.BoolVar(&opts.noNormalize, "no-normalize", false, "Don't normalize compose model.")
|
||||
flags.BoolVar(&opts.noResolvePath, "no-path-resolution", false, "Don't resolve file paths.")
|
||||
flags.BoolVar(&opts.noConsistency, "no-consistency", false, "Don't check model consistency - warning: may produce invalid Compose output")
|
||||
|
||||
flags.BoolVar(&opts.services, "services", false, "Print the service names, one per line.")
|
||||
@@ -110,20 +120,14 @@ func convertCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runConvert(ctx context.Context, backend api.Service, opts convertOptions, services []string) error {
|
||||
func runConfig(ctx context.Context, streams api.Streams, backend api.Service, opts configOptions, services []string) error {
|
||||
var content []byte
|
||||
project, err := opts.toProject(services,
|
||||
cli.WithInterpolation(!opts.noInterpolate),
|
||||
cli.WithResolvedPaths(true),
|
||||
cli.WithNormalization(!opts.noNormalize),
|
||||
cli.WithConsistency(!opts.noConsistency),
|
||||
cli.WithDiscardEnvFile)
|
||||
|
||||
project, err := opts.ToProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
content, err = backend.Convert(ctx, project, api.ConvertOptions{
|
||||
content, err = backend.Config(ctx, project, api.ConfigOptions{
|
||||
Format: opts.Format,
|
||||
Output: opts.Output,
|
||||
ResolveImageDigests: opts.resolveImageDigests,
|
||||
@@ -140,62 +144,70 @@ func runConvert(ctx context.Context, backend api.Service, opts convertOptions, s
|
||||
return nil
|
||||
}
|
||||
|
||||
var out io.Writer = os.Stdout
|
||||
if opts.Output != "" && len(content) > 0 {
|
||||
file, err := os.Create(opts.Output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out = bufio.NewWriter(file)
|
||||
return os.WriteFile(opts.Output, content, 0o666)
|
||||
}
|
||||
_, err = fmt.Fprint(out, string(content))
|
||||
_, err = fmt.Fprint(streams.Out(), string(content))
|
||||
return err
|
||||
}
|
||||
|
||||
func runServices(opts convertOptions) error {
|
||||
project, err := opts.toProject(nil)
|
||||
func runServices(streams api.Streams, opts configOptions) error {
|
||||
project, err := opts.ToProject(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return project.WithServices(project.ServiceNames(), func(s types.ServiceConfig) error {
|
||||
fmt.Println(s.Name)
|
||||
fmt.Fprintln(streams.Out(), s.Name)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func runVolumes(opts convertOptions) error {
|
||||
project, err := opts.toProject(nil)
|
||||
func runVolumes(streams api.Streams, opts configOptions) error {
|
||||
project, err := opts.ToProject(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for n := range project.Volumes {
|
||||
fmt.Println(n)
|
||||
fmt.Fprintln(streams.Out(), n)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runHash(opts convertOptions) error {
|
||||
func runHash(streams api.Streams, opts configOptions) error {
|
||||
var services []string
|
||||
if opts.hash != "*" {
|
||||
services = append(services, strings.Split(opts.hash, ",")...)
|
||||
}
|
||||
project, err := opts.toProject(services)
|
||||
project, err := opts.ToProject(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range project.Services {
|
||||
|
||||
if len(services) > 0 {
|
||||
err = project.ForServices(services, types.IgnoreDependencies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
sorted := project.Services
|
||||
sort.Slice(sorted, func(i, j int) bool {
|
||||
return sorted[i].Name < sorted[j].Name
|
||||
})
|
||||
|
||||
for _, s := range sorted {
|
||||
hash, err := compose.ServiceHash(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%s %s\n", s.Name, hash)
|
||||
fmt.Fprintf(streams.Out(), "%s %s\n", s.Name, hash)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runProfiles(opts convertOptions, services []string) error {
|
||||
func runProfiles(streams api.Streams, opts configOptions, services []string) error {
|
||||
set := map[string]struct{}{}
|
||||
project, err := opts.toProject(services)
|
||||
project, err := opts.ToProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -210,22 +222,18 @@ func runProfiles(opts convertOptions, services []string) error {
|
||||
}
|
||||
sort.Strings(profiles)
|
||||
for _, p := range profiles {
|
||||
fmt.Println(p)
|
||||
fmt.Fprintln(streams.Out(), p)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runConfigImages(opts convertOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
func runConfigImages(streams api.Streams, opts configOptions, services []string) error {
|
||||
project, err := opts.ToProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range project.Services {
|
||||
if s.Image != "" {
|
||||
fmt.Println(s.Image)
|
||||
} else {
|
||||
fmt.Printf("%s%s%s\n", project.Name, api.Separator, s.Name)
|
||||
}
|
||||
fmt.Fprintln(streams.Out(), api.GetImageNameOrDefault(s, project.Name))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
)
|
||||
|
||||
type copyOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
|
||||
source string
|
||||
destination string
|
||||
@@ -37,9 +37,9 @@ type copyOptions struct {
|
||||
copyUIDGID bool
|
||||
}
|
||||
|
||||
func copyCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func copyCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := copyOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
copyCmd := &cobra.Command{
|
||||
Use: `cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|-
|
||||
@@ -64,10 +64,10 @@ func copyCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
flags := copyCmd.Flags()
|
||||
flags.IntVar(&opts.index, "index", 0, "Index of the container if there are multiple instances of a service .")
|
||||
flags.BoolVar(&opts.all, "all", false, "Copy to all the containers of the service.")
|
||||
flags.IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas")
|
||||
flags.BoolVar(&opts.all, "all", false, "copy to all the containers of the service.")
|
||||
flags.MarkHidden("all") //nolint:errcheck
|
||||
flags.MarkDeprecated("all", "By default all the containers of the service will get the source file/directory to be copied.") //nolint:errcheck
|
||||
flags.MarkDeprecated("all", "by default all the containers of the service will get the source file/directory to be copied.") //nolint:errcheck
|
||||
flags.BoolVarP(&opts.followLink, "follow-link", "L", false, "Always follow symbol link in SRC_PATH")
|
||||
flags.BoolVarP(&opts.copyUIDGID, "archive", "a", false, "Archive mode (copy all uid/gid information)")
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ package compose
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
@@ -41,9 +43,10 @@ type createOptions struct {
|
||||
timeChanged bool
|
||||
timeout int
|
||||
quietPull bool
|
||||
scale []string
|
||||
}
|
||||
|
||||
func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func createCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := createOptions{}
|
||||
cmd := &cobra.Command{
|
||||
Use: "create [OPTIONS] [SERVICE...]",
|
||||
@@ -59,7 +62,9 @@ func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
return nil
|
||||
}),
|
||||
RunE: p.WithProject(func(ctx context.Context, project *types.Project) error {
|
||||
opts.Apply(project)
|
||||
if err := opts.Apply(project); err != nil {
|
||||
return err
|
||||
}
|
||||
return backend.Create(ctx, project, api.CreateOptions{
|
||||
RemoveOrphans: opts.removeOrphans,
|
||||
IgnoreOrphans: opts.ignoreOrphans,
|
||||
@@ -78,6 +83,8 @@ func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
flags.StringVar(&opts.Pull, "pull", "missing", `Pull image before running ("always"|"missing"|"never")`)
|
||||
flags.BoolVar(&opts.forceRecreate, "force-recreate", false, "Recreate containers even if their configuration and image haven't changed.")
|
||||
flags.BoolVar(&opts.noRecreate, "no-recreate", false, "If containers already exist, don't recreate them. Incompatible with --force-recreate.")
|
||||
flags.BoolVar(&opts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
|
||||
flags.StringArrayVar(&opts.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -109,7 +116,7 @@ func (opts createOptions) GetTimeout() *time.Duration {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opts createOptions) Apply(project *types.Project) {
|
||||
func (opts createOptions) Apply(project *types.Project) error {
|
||||
if opts.pullChanged {
|
||||
for i, service := range project.Services {
|
||||
service.PullPolicy = opts.Pull
|
||||
@@ -134,4 +141,20 @@ func (opts createOptions) Apply(project *types.Project) {
|
||||
project.Services[i] = service
|
||||
}
|
||||
}
|
||||
for _, scale := range opts.scale {
|
||||
split := strings.Split(scale, "=")
|
||||
if len(split) != 2 {
|
||||
return fmt.Errorf("invalid --scale option %q. Should be SERVICE=NUM", scale)
|
||||
}
|
||||
name := split[0]
|
||||
replicas, err := strconv.Atoi(split[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = setServiceScale(project, name, uint64(replicas))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import (
|
||||
)
|
||||
|
||||
type downOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
removeOrphans bool
|
||||
timeChanged bool
|
||||
timeout int
|
||||
@@ -39,12 +39,12 @@ type downOptions struct {
|
||||
images string
|
||||
}
|
||||
|
||||
func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func downCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := downOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
downCmd := &cobra.Command{
|
||||
Use: "down [OPTIONS]",
|
||||
Use: "down [OPTIONS] [SERVICES]",
|
||||
Short: "Stop and remove containers, networks",
|
||||
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||
@@ -56,16 +56,15 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
return nil
|
||||
}),
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runDown(ctx, backend, opts)
|
||||
return runDown(ctx, backend, opts, args)
|
||||
}),
|
||||
Args: cobra.NoArgs,
|
||||
ValidArgsFunction: noCompletion(),
|
||||
}
|
||||
flags := downCmd.Flags()
|
||||
removeOrphans := utils.StringToBool(os.Getenv("COMPOSE_REMOVE_ORPHANS"))
|
||||
removeOrphans := utils.StringToBool(os.Getenv(ComposeRemoveOrphans))
|
||||
flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.")
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
|
||||
flags.BoolVarP(&opts.volumes, "volumes", "v", false, "Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.")
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 0, "Specify a shutdown timeout in seconds")
|
||||
flags.BoolVarP(&opts.volumes, "volumes", "v", false, `Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers.`)
|
||||
flags.StringVar(&opts.images, "rmi", "", `Remove images used by services. "local" remove only images that don't have a custom tag ("local"|"all")`)
|
||||
flags.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
if name == "volume" {
|
||||
@@ -77,7 +76,7 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
return downCmd
|
||||
}
|
||||
|
||||
func runDown(ctx context.Context, backend api.Service, opts downOptions) error {
|
||||
func runDown(ctx context.Context, backend api.Service, opts downOptions, services []string) error {
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -94,5 +93,6 @@ func runDown(ctx context.Context, backend api.Service, opts downOptions) error {
|
||||
Timeout: timeout,
|
||||
Images: opts.images,
|
||||
Volumes: opts.volumes,
|
||||
Services: services,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,17 +31,17 @@ type eventsOpts struct {
|
||||
json bool
|
||||
}
|
||||
|
||||
func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func eventsCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
opts := eventsOpts{
|
||||
composeOptions: &composeOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
},
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "events [OPTIONS] [SERVICE...]",
|
||||
Short: "Receive real time events from containers.",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runEvents(ctx, backend, opts, args)
|
||||
return runEvents(ctx, streams, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, services []string) error {
|
||||
func runEvents(ctx context.Context, streams api.Streams, backend api.Service, opts eventsOpts, services []string) error {
|
||||
name, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -71,9 +71,9 @@ func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, servic
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(string(marshal))
|
||||
fmt.Fprintln(streams.Out(), string(marshal))
|
||||
} else {
|
||||
fmt.Println(event)
|
||||
fmt.Fprintln(streams.Out(), event)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/compose"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -43,10 +42,10 @@ type execOpts struct {
|
||||
interactive bool
|
||||
}
|
||||
|
||||
func execCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
func execCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
opts := execOpts{
|
||||
composeOptions: &composeOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
},
|
||||
}
|
||||
runCmd := &cobra.Command{
|
||||
@@ -66,10 +65,10 @@ func execCommand(p *projectOptions, dockerCli command.Cli, backend api.Service)
|
||||
|
||||
runCmd.Flags().BoolVarP(&opts.detach, "detach", "d", false, "Detached mode: Run command in the background.")
|
||||
runCmd.Flags().StringArrayVarP(&opts.environment, "env", "e", []string{}, "Set environment variables")
|
||||
runCmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if there are multiple instances of a service [default: 1].")
|
||||
runCmd.Flags().IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas")
|
||||
runCmd.Flags().BoolVarP(&opts.privileged, "privileged", "", false, "Give extended privileges to the process.")
|
||||
runCmd.Flags().StringVarP(&opts.user, "user", "u", "", "Run the command as this user.")
|
||||
runCmd.Flags().BoolVarP(&opts.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.")
|
||||
runCmd.Flags().BoolVarP(&opts.noTty, "no-TTY", "T", !streams.Out().IsTerminal(), "Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.")
|
||||
runCmd.Flags().StringVarP(&opts.workingDir, "workdir", "w", "", "Path to workdir directory for this command.")
|
||||
|
||||
runCmd.Flags().BoolVarP(&opts.interactive, "interactive", "i", true, "Keep STDIN open even if not attached.")
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -34,27 +33,29 @@ import (
|
||||
)
|
||||
|
||||
type imageOptions struct {
|
||||
*projectOptions
|
||||
Quiet bool
|
||||
*ProjectOptions
|
||||
Quiet bool
|
||||
Format string
|
||||
}
|
||||
|
||||
func imagesCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func imagesCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
opts := imageOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
imgCmd := &cobra.Command{
|
||||
Use: "images [OPTIONS] [SERVICE...]",
|
||||
Short: "List images used by the created containers",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runImages(ctx, backend, opts, args)
|
||||
return runImages(ctx, streams, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
imgCmd.Flags().StringVar(&opts.Format, "format", "table", "Format the output. Values: [table | json].")
|
||||
imgCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
|
||||
return imgCmd
|
||||
}
|
||||
|
||||
func runImages(ctx context.Context, backend api.Service, opts imageOptions, services []string) error {
|
||||
func runImages(ctx context.Context, streams api.Streams, backend api.Service, opts imageOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -79,7 +80,7 @@ func runImages(ctx context.Context, backend api.Service, opts imageOptions, serv
|
||||
}
|
||||
}
|
||||
for _, img := range ids {
|
||||
fmt.Println(img)
|
||||
fmt.Fprintln(streams.Out(), img)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -88,7 +89,7 @@ func runImages(ctx context.Context, backend api.Service, opts imageOptions, serv
|
||||
return images[i].ContainerName < images[j].ContainerName
|
||||
})
|
||||
|
||||
return formatter.Print(images, formatter.PRETTY, os.Stdout,
|
||||
return formatter.Print(images, opts.Format, streams.Out(),
|
||||
func(w io.Writer) {
|
||||
for _, img := range images {
|
||||
id := stringid.TruncateID(img.ID)
|
||||
@@ -104,5 +105,5 @@ func runImages(ctx context.Context, backend api.Service, opts imageOptions, serv
|
||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", img.ContainerName, repo, tag, id, size)
|
||||
}
|
||||
},
|
||||
"Container", "Repository", "Tag", "Image Id", "Size")
|
||||
"CONTAINER", "REPOSITORY", "TAG", "IMAGE ID", "SIZE")
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@ import (
|
||||
)
|
||||
|
||||
type killOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
removeOrphans bool
|
||||
signal string
|
||||
}
|
||||
|
||||
func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func killCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := killOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "kill [OPTIONS] [SERVICE...]",
|
||||
@@ -46,7 +46,7 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
removeOrphans := utils.StringToBool(os.Getenv("COMPOSE_REMOVE_ORPHANS"))
|
||||
removeOrphans := utils.StringToBool(os.Getenv(ComposeRemoveOrphans))
|
||||
flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.")
|
||||
flags.StringVarP(&opts.signal, "signal", "s", "SIGKILL", "SIGNAL to send to the container.")
|
||||
|
||||
@@ -65,5 +65,4 @@ func runKill(ctx context.Context, backend api.Service, opts killOptions, service
|
||||
Services: services,
|
||||
Signal: opts.signal,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
@@ -38,18 +37,18 @@ type lsOptions struct {
|
||||
Filter opts.FilterOpt
|
||||
}
|
||||
|
||||
func listCommand(backend api.Service) *cobra.Command {
|
||||
func listCommand(streams api.Streams, backend api.Service) *cobra.Command {
|
||||
lsOpts := lsOptions{Filter: opts.NewFilterOpt()}
|
||||
lsCmd := &cobra.Command{
|
||||
Use: "ls [OPTIONS]",
|
||||
Short: "List running compose projects",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runList(ctx, backend, lsOpts)
|
||||
return runList(ctx, streams, backend, lsOpts)
|
||||
}),
|
||||
Args: cobra.NoArgs,
|
||||
ValidArgsFunction: noCompletion(),
|
||||
}
|
||||
lsCmd.Flags().StringVar(&lsOpts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
|
||||
lsCmd.Flags().StringVar(&lsOpts.Format, "format", "table", "Format the output. Values: [table | json].")
|
||||
lsCmd.Flags().BoolVarP(&lsOpts.Quiet, "quiet", "q", false, "Only display IDs.")
|
||||
lsCmd.Flags().Var(&lsOpts.Filter, "filter", "Filter output based on conditions provided.")
|
||||
lsCmd.Flags().BoolVarP(&lsOpts.All, "all", "a", false, "Show all stopped Compose projects")
|
||||
@@ -61,7 +60,7 @@ var acceptedListFilters = map[string]bool{
|
||||
"name": true,
|
||||
}
|
||||
|
||||
func runList(ctx context.Context, backend api.Service, lsOpts lsOptions) error {
|
||||
func runList(ctx context.Context, streams api.Streams, backend api.Service, lsOpts lsOptions) error {
|
||||
filters := lsOpts.Filter.Value()
|
||||
err := filters.Validate(acceptedListFilters)
|
||||
if err != nil {
|
||||
@@ -74,7 +73,7 @@ func runList(ctx context.Context, backend api.Service, lsOpts lsOptions) error {
|
||||
}
|
||||
if lsOpts.Quiet {
|
||||
for _, s := range stackList {
|
||||
fmt.Println(s.Name)
|
||||
fmt.Fprintln(streams.Out(), s.Name)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -91,7 +90,7 @@ func runList(ctx context.Context, backend api.Service, lsOpts lsOptions) error {
|
||||
}
|
||||
|
||||
view := viewFromStackList(stackList)
|
||||
return formatter.Print(view, lsOpts.Format, os.Stdout, func(w io.Writer) {
|
||||
return formatter.Print(view, lsOpts.Format, streams.Out(), func(w io.Writer) {
|
||||
for _, stack := range view {
|
||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", stack.Name, stack.Status, stack.ConfigFiles)
|
||||
}
|
||||
|
||||
@@ -18,17 +18,15 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
)
|
||||
|
||||
type logsOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
composeOptions
|
||||
follow bool
|
||||
tail string
|
||||
@@ -39,15 +37,15 @@ type logsOptions struct {
|
||||
timestamps bool
|
||||
}
|
||||
|
||||
func logsCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func logsCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
opts := logsOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
logsCmd := &cobra.Command{
|
||||
Use: "logs [OPTIONS] [SERVICE...]",
|
||||
Short: "View output from containers",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runLogs(ctx, backend, opts, args)
|
||||
return runLogs(ctx, streams, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
@@ -58,16 +56,16 @@ func logsCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
flags.BoolVar(&opts.noColor, "no-color", false, "Produce monochrome output.")
|
||||
flags.BoolVar(&opts.noPrefix, "no-log-prefix", false, "Don't print prefix in logs.")
|
||||
flags.BoolVarP(&opts.timestamps, "timestamps", "t", false, "Show timestamps.")
|
||||
flags.StringVar(&opts.tail, "tail", "all", "Number of lines to show from the end of the logs for each container.")
|
||||
flags.StringVarP(&opts.tail, "tail", "n", "all", "Number of lines to show from the end of the logs for each container.")
|
||||
return logsCmd
|
||||
}
|
||||
|
||||
func runLogs(ctx context.Context, backend api.Service, opts logsOptions, services []string) error {
|
||||
func runLogs(ctx context.Context, streams api.Streams, backend api.Service, opts logsOptions, services []string) error {
|
||||
project, name, err := opts.projectOrName(services...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
consumer := formatter.NewLogConsumer(ctx, os.Stdout, !opts.noColor, !opts.noPrefix)
|
||||
consumer := formatter.NewLogConsumer(ctx, streams.Out(), streams.Err(), !opts.noColor, !opts.noPrefix, false)
|
||||
return backend.Logs(ctx, name, consumer, api.LogOptions{
|
||||
Project: project,
|
||||
Services: services,
|
||||
|
||||
@@ -25,12 +25,12 @@ import (
|
||||
)
|
||||
|
||||
type pauseOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
}
|
||||
|
||||
func pauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func pauseCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := pauseOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "pause [SERVICE...]",
|
||||
@@ -56,12 +56,12 @@ func runPause(ctx context.Context, backend api.Service, opts pauseOptions, servi
|
||||
}
|
||||
|
||||
type unpauseOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
}
|
||||
|
||||
func unpauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func unpauseCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := unpauseOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "unpause [SERVICE...]",
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -27,39 +28,40 @@ import (
|
||||
)
|
||||
|
||||
type portOptions struct {
|
||||
*projectOptions
|
||||
port int
|
||||
*ProjectOptions
|
||||
port uint16
|
||||
protocol string
|
||||
index int
|
||||
}
|
||||
|
||||
func portCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func portCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
opts := portOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "port [OPTIONS] SERVICE PRIVATE_PORT",
|
||||
Short: "Print the public port for a port binding.",
|
||||
Args: cobra.MinimumNArgs(2),
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
port, err := strconv.Atoi(args[1])
|
||||
port, err := strconv.ParseUint(args[1], 10, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts.port = port
|
||||
opts.port = uint16(port)
|
||||
opts.protocol = strings.ToLower(opts.protocol)
|
||||
return nil
|
||||
}),
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runPort(ctx, backend, opts, args[0])
|
||||
return runPort(ctx, streams, backend, opts, args[0])
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
cmd.Flags().StringVar(&opts.protocol, "protocol", "tcp", "tcp or udp")
|
||||
cmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if service has multiple replicas")
|
||||
cmd.Flags().IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runPort(ctx context.Context, backend api.Service, opts portOptions, service string) error {
|
||||
func runPort(ctx context.Context, streams api.Streams, backend api.Service, opts portOptions, service string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -72,6 +74,6 @@ func runPort(ctx context.Context, backend api.Service, opts portOptions, service
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("%s:%d\n", ip, port)
|
||||
fmt.Fprintf(streams.Out(), "%s:%d\n", ip, port)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -20,16 +20,17 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
"github.com/docker/docker/api/types"
|
||||
|
||||
formatter2 "github.com/docker/cli/cli/command/formatter"
|
||||
"github.com/docker/go-units"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -37,7 +38,7 @@ import (
|
||||
)
|
||||
|
||||
type psOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
Format string
|
||||
All bool
|
||||
Quiet bool
|
||||
@@ -65,9 +66,9 @@ func (p *psOptions) parseFilter() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func psCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
opts := psOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
psCmd := &cobra.Command{
|
||||
Use: "ps [OPTIONS] [SERVICE...]",
|
||||
@@ -76,12 +77,12 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
return opts.parseFilter()
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runPs(ctx, backend, args, opts)
|
||||
return runPs(ctx, streams, backend, args, opts)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
flags := psCmd.Flags()
|
||||
flags.StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json]")
|
||||
flags.StringVar(&opts.Format, "format", "table", "Format the output. Values: [table | json]")
|
||||
flags.StringVar(&opts.Filter, "filter", "", "Filter services by a property (supported filters: status).")
|
||||
flags.StringArrayVar(&opts.Status, "status", []string{}, "Filter services by status. Values: [paused | restarting | removing | running | dead | created | exited]")
|
||||
flags.BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs")
|
||||
@@ -90,11 +91,21 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
return psCmd
|
||||
}
|
||||
|
||||
func runPs(ctx context.Context, backend api.Service, services []string, opts psOptions) error {
|
||||
func runPs(ctx context.Context, streams api.Streams, backend api.Service, services []string, opts psOptions) error {
|
||||
project, name, err := opts.projectOrName(services...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if project != nil && len(services) > 0 {
|
||||
names := project.ServiceNames()
|
||||
for _, service := range services {
|
||||
if !utils.StringContains(names, service) {
|
||||
return fmt.Errorf("no such service: %s", service)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
containers, err := backend.Ps(ctx, name, api.PsOptions{
|
||||
Project: project,
|
||||
All: opts.All,
|
||||
@@ -104,16 +115,6 @@ func runPs(ctx context.Context, backend api.Service, services []string, opts psO
|
||||
return err
|
||||
}
|
||||
|
||||
SERVICES:
|
||||
for _, s := range services {
|
||||
for _, c := range containers {
|
||||
if c.Service == s {
|
||||
continue SERVICES
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("no such service: %s", s)
|
||||
}
|
||||
|
||||
if len(opts.Status) != 0 {
|
||||
containers = filterByStatus(containers, opts.Status)
|
||||
}
|
||||
@@ -124,7 +125,7 @@ SERVICES:
|
||||
|
||||
if opts.Quiet {
|
||||
for _, c := range containers {
|
||||
fmt.Println(c.ID)
|
||||
fmt.Fprintln(streams.Out(), c.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -136,27 +137,24 @@ SERVICES:
|
||||
services = append(services, s.Service)
|
||||
}
|
||||
}
|
||||
fmt.Println(strings.Join(services, "\n"))
|
||||
fmt.Fprintln(streams.Out(), strings.Join(services, "\n"))
|
||||
return nil
|
||||
}
|
||||
|
||||
return formatter.Print(containers, opts.Format, os.Stdout,
|
||||
return formatter.Print(containers, opts.Format, streams.Out(),
|
||||
writer(containers),
|
||||
"NAME", "COMMAND", "SERVICE", "STATUS", "PORTS")
|
||||
"NAME", "IMAGE", "COMMAND", "SERVICE", "CREATED", "STATUS", "PORTS")
|
||||
}
|
||||
|
||||
func writer(containers []api.ContainerSummary) func(w io.Writer) {
|
||||
return func(w io.Writer) {
|
||||
for _, container := range containers {
|
||||
ports := displayablePorts(container)
|
||||
status := container.State
|
||||
if status == "running" && container.Health != "" {
|
||||
status = fmt.Sprintf("%s (%s)", container.State, container.Health)
|
||||
} else if status == "exited" || status == "dead" {
|
||||
status = fmt.Sprintf("%s (%d)", container.State, container.ExitCode)
|
||||
}
|
||||
createdAt := time.Unix(container.Created, 0)
|
||||
created := units.HumanDuration(time.Now().UTC().Sub(createdAt)) + " ago"
|
||||
status := container.Status
|
||||
command := formatter2.Ellipsis(container.Command, 20)
|
||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n", container.Name, strconv.Quote(command), container.Service, status, ports)
|
||||
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", container.Name, container.Image, strconv.Quote(command), container.Service, created, status, ports)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,30 +18,28 @@ package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/streams"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/mocks"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPsPretty(t *testing.T) {
|
||||
func TestPsTable(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
origStdout := os.Stdout
|
||||
t.Cleanup(func() {
|
||||
os.Stdout = origStdout
|
||||
})
|
||||
dir := t.TempDir()
|
||||
f, err := os.Create(filepath.Join(dir, "output.txt"))
|
||||
out := filepath.Join(dir, "output.txt")
|
||||
f, err := os.Create(out)
|
||||
if err != nil {
|
||||
t.Fatal("could not create output file")
|
||||
}
|
||||
defer func() { _ = f.Close() }()
|
||||
|
||||
os.Stdout = f
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
@@ -51,8 +49,9 @@ func TestPsPretty(t *testing.T) {
|
||||
DoAndReturn(func(ctx context.Context, projectName string, options api.PsOptions) ([]api.ContainerSummary, error) {
|
||||
return []api.ContainerSummary{
|
||||
{
|
||||
ID: "abc123",
|
||||
Name: "ABC",
|
||||
ID: "abc123",
|
||||
Name: "ABC",
|
||||
Image: "foo/bar",
|
||||
Publishers: api.PortPublishers{
|
||||
{
|
||||
TargetPort: 8080,
|
||||
@@ -69,16 +68,33 @@ func TestPsPretty(t *testing.T) {
|
||||
}, nil
|
||||
}).AnyTimes()
|
||||
|
||||
opts := psOptions{projectOptions: &projectOptions{ProjectName: "test"}}
|
||||
err = runPs(ctx, backend, nil, opts)
|
||||
opts := psOptions{ProjectOptions: &ProjectOptions{ProjectName: "test"}}
|
||||
err = runPs(ctx, stream{out: streams.NewOut(f)}, backend, nil, opts)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = f.Seek(0, 0)
|
||||
assert.NoError(t, err)
|
||||
|
||||
output := make([]byte, 256)
|
||||
_, err = f.Read(output)
|
||||
output, err := os.ReadFile(out)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Contains(t, string(output), "8080/tcp, 8443/tcp")
|
||||
}
|
||||
|
||||
type stream struct {
|
||||
out *streams.Out
|
||||
err io.Writer
|
||||
in *streams.In
|
||||
}
|
||||
|
||||
func (s stream) Out() *streams.Out {
|
||||
return s.out
|
||||
}
|
||||
|
||||
func (s stream) Err() io.Writer {
|
||||
return s.err
|
||||
}
|
||||
|
||||
func (s stream) In() *streams.In {
|
||||
return s.in
|
||||
}
|
||||
|
||||
49
cmd/compose/publish.go
Normal file
49
cmd/compose/publish.go
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
)
|
||||
|
||||
func publishCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := pushOptions{
|
||||
ProjectOptions: p,
|
||||
}
|
||||
publishCmd := &cobra.Command{
|
||||
Use: "publish [OPTIONS] [REPOSITORY]",
|
||||
Short: "Publish compose application",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runPublish(ctx, backend, opts, args[0])
|
||||
}),
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
return publishCmd
|
||||
}
|
||||
|
||||
func runPublish(ctx context.Context, backend api.Service, opts pushOptions, repository string) error {
|
||||
project, err := opts.ToProject(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return backend.Publish(ctx, project, repository)
|
||||
}
|
||||
@@ -21,26 +21,27 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/morikuni/aec"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/compose/v2/pkg/utils"
|
||||
)
|
||||
|
||||
type pullOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
composeOptions
|
||||
quiet bool
|
||||
parallel bool
|
||||
noParallel bool
|
||||
includeDeps bool
|
||||
ignorePullFailures bool
|
||||
noBuildable bool
|
||||
}
|
||||
|
||||
func pullCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func pullCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := pullOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "pull [OPTIONS] [SERVICE...]",
|
||||
@@ -57,37 +58,33 @@ func pullCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Pull without printing progress information")
|
||||
cmd.Flags().BoolVar(&opts.includeDeps, "include-deps", false, "Also pull services declared as dependencies")
|
||||
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Pull without printing progress information.")
|
||||
cmd.Flags().BoolVar(&opts.includeDeps, "include-deps", false, "Also pull services declared as dependencies.")
|
||||
cmd.Flags().BoolVar(&opts.parallel, "parallel", true, "DEPRECATED pull multiple images in parallel.")
|
||||
flags.MarkHidden("parallel") //nolint:errcheck
|
||||
cmd.Flags().BoolVar(&opts.parallel, "no-parallel", true, "DEPRECATED disable parallel pulling.")
|
||||
flags.MarkHidden("no-parallel") //nolint:errcheck
|
||||
cmd.Flags().BoolVar(&opts.ignorePullFailures, "ignore-pull-failures", false, "Pull what it can and ignores images with pull failures")
|
||||
cmd.Flags().BoolVar(&opts.ignorePullFailures, "ignore-pull-failures", false, "Pull what it can and ignores images with pull failures.")
|
||||
cmd.Flags().BoolVar(&opts.noBuildable, "ignore-buildable", false, "Ignore images that can be built.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runPull(ctx context.Context, backend api.Service, opts pullOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
project, err := opts.ToProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !opts.includeDeps {
|
||||
enabled, err := project.GetServices(services...)
|
||||
err := project.ForServices(services, types.IgnoreDependencies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range project.Services {
|
||||
if !utils.StringContains(services, s.Name) {
|
||||
project.DisabledServices = append(project.DisabledServices, s)
|
||||
}
|
||||
}
|
||||
project.Services = enabled
|
||||
}
|
||||
|
||||
return backend.Pull(ctx, project, api.PullOptions{
|
||||
Quiet: opts.quiet,
|
||||
IgnoreFailures: opts.ignorePullFailures,
|
||||
Quiet: opts.quiet,
|
||||
IgnoreFailures: opts.ignorePullFailures,
|
||||
IgnoreBuildable: opts.noBuildable,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -19,22 +19,23 @@ package compose
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
)
|
||||
|
||||
type pushOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
composeOptions
|
||||
|
||||
IncludeDeps bool
|
||||
Ignorefailures bool
|
||||
Quiet bool
|
||||
}
|
||||
|
||||
func pushCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func pushCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := pushOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
pushCmd := &cobra.Command{
|
||||
Use: "push [OPTIONS] [SERVICE...]",
|
||||
@@ -45,17 +46,25 @@ func pushCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
pushCmd.Flags().BoolVar(&opts.Ignorefailures, "ignore-push-failures", false, "Push what it can and ignores images with push failures")
|
||||
pushCmd.Flags().BoolVar(&opts.IncludeDeps, "include-deps", false, "Also push images of services declared as dependencies")
|
||||
pushCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Push without printing progress information")
|
||||
|
||||
return pushCmd
|
||||
}
|
||||
|
||||
func runPush(ctx context.Context, backend api.Service, opts pushOptions, services []string) error {
|
||||
project, err := opts.toProject(services)
|
||||
project, err := opts.ToProject(services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !opts.IncludeDeps {
|
||||
err := project.ForServices(services, types.IgnoreDependencies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return backend.Push(ctx, project, api.PushOptions{
|
||||
IgnoreFailures: opts.Ignorefailures,
|
||||
Quiet: opts.Quiet,
|
||||
|
||||
@@ -24,15 +24,15 @@ import (
|
||||
)
|
||||
|
||||
type removeOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
force bool
|
||||
stop bool
|
||||
volumes bool
|
||||
}
|
||||
|
||||
func removeCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func removeCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := removeOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "rm [OPTIONS] [SERVICE...]",
|
||||
@@ -64,20 +64,11 @@ func runRemove(ctx context.Context, backend api.Service, opts removeOptions, ser
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.stop {
|
||||
err := backend.Stop(ctx, name, api.StopOptions{
|
||||
Services: services,
|
||||
Project: project,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return backend.Remove(ctx, name, api.RemoveOptions{
|
||||
Services: services,
|
||||
Force: opts.force,
|
||||
Volumes: opts.volumes,
|
||||
Project: project,
|
||||
Stop: opts.stop,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -20,43 +20,62 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
)
|
||||
|
||||
type restartOptions struct {
|
||||
*projectOptions
|
||||
timeout int
|
||||
*ProjectOptions
|
||||
timeChanged bool
|
||||
timeout int
|
||||
noDeps bool
|
||||
}
|
||||
|
||||
func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func restartCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := restartOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
restartCmd := &cobra.Command{
|
||||
Use: "restart [OPTIONS] [SERVICE...]",
|
||||
Short: "Restart service containers",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
opts.timeChanged = cmd.Flags().Changed("timeout")
|
||||
},
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runRestart(ctx, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
flags := restartCmd.Flags()
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 0, "Specify a shutdown timeout in seconds")
|
||||
flags.BoolVar(&opts.noDeps, "no-deps", false, "Don't restart dependent services.")
|
||||
|
||||
return restartCmd
|
||||
}
|
||||
|
||||
func runRestart(ctx context.Context, backend api.Service, opts restartOptions, services []string) error {
|
||||
project, name, err := opts.projectOrName(services...)
|
||||
project, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
timeout := time.Duration(opts.timeout) * time.Second
|
||||
var timeout *time.Duration
|
||||
if opts.timeChanged {
|
||||
timeoutValue := time.Duration(opts.timeout) * time.Second
|
||||
timeout = &timeoutValue
|
||||
}
|
||||
|
||||
if opts.noDeps {
|
||||
err := project.ForServices(services, types.IgnoreDependencies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return backend.Restart(ctx, name, api.RestartOptions{
|
||||
Timeout: &timeout,
|
||||
Timeout: timeout,
|
||||
Services: services,
|
||||
Project: project,
|
||||
})
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
cgo "github.com/compose-spec/compose-go/cli"
|
||||
"github.com/compose-spec/compose-go/loader"
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/opts"
|
||||
"github.com/mattn/go-shellwords"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
@@ -43,11 +43,14 @@ type runOptions struct {
|
||||
Detach bool
|
||||
Remove bool
|
||||
noTty bool
|
||||
tty bool
|
||||
interactive bool
|
||||
user string
|
||||
workdir string
|
||||
entrypoint string
|
||||
entrypointCmd []string
|
||||
capAdd opts.ListOpts
|
||||
capDrop opts.ListOpts
|
||||
labels []string
|
||||
volumes []string
|
||||
publish []string
|
||||
@@ -59,20 +62,27 @@ type runOptions struct {
|
||||
quietPull bool
|
||||
}
|
||||
|
||||
func (opts runOptions) apply(project *types.Project) error {
|
||||
target, err := project.GetService(opts.Service)
|
||||
func (options runOptions) apply(project *types.Project) error {
|
||||
if options.noDeps {
|
||||
err := project.ForServices([]string{options.Service}, types.IgnoreDependencies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
target, err := project.GetService(options.Service)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
target.Tty = !opts.noTty
|
||||
target.StdinOpen = opts.interactive
|
||||
if !opts.servicePorts {
|
||||
target.Tty = !options.noTty
|
||||
target.StdinOpen = options.interactive
|
||||
if !options.servicePorts {
|
||||
target.Ports = []types.ServicePortConfig{}
|
||||
}
|
||||
if len(opts.publish) > 0 {
|
||||
if len(options.publish) > 0 {
|
||||
target.Ports = []types.ServicePortConfig{}
|
||||
for _, p := range opts.publish {
|
||||
for _, p := range options.publish {
|
||||
config, err := types.ParsePortConfig(p)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -80,8 +90,8 @@ func (opts runOptions) apply(project *types.Project) error {
|
||||
target.Ports = append(target.Ports, config...)
|
||||
}
|
||||
}
|
||||
if len(opts.volumes) > 0 {
|
||||
for _, v := range opts.volumes {
|
||||
if len(options.volumes) > 0 {
|
||||
for _, v := range options.volumes {
|
||||
volume, err := loader.ParseVolume(v)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -90,17 +100,8 @@ func (opts runOptions) apply(project *types.Project) error {
|
||||
}
|
||||
}
|
||||
|
||||
if opts.noDeps {
|
||||
for _, s := range project.Services {
|
||||
if s.Name != opts.Service {
|
||||
project.DisabledServices = append(project.DisabledServices, s)
|
||||
}
|
||||
}
|
||||
project.Services = types.Services{target}
|
||||
}
|
||||
|
||||
for i, s := range project.Services {
|
||||
if s.Name == opts.Service {
|
||||
if s.Name == options.Service {
|
||||
project.Services[i] = target
|
||||
break
|
||||
}
|
||||
@@ -108,11 +109,13 @@ func (opts runOptions) apply(project *types.Project) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
|
||||
opts := runOptions{
|
||||
func runCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
options := runOptions{
|
||||
composeOptions: &composeOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
},
|
||||
capAdd: opts.NewListOpts(nil),
|
||||
capDrop: opts.NewListOpts(nil),
|
||||
}
|
||||
createOpts := createOptions{}
|
||||
cmd := &cobra.Command{
|
||||
@@ -120,52 +123,63 @@ func runCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *
|
||||
Short: "Run a one-off command on a service.",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
opts.Service = args[0]
|
||||
options.Service = args[0]
|
||||
if len(args) > 1 {
|
||||
opts.Command = args[1:]
|
||||
options.Command = args[1:]
|
||||
}
|
||||
if len(opts.publish) > 0 && opts.servicePorts {
|
||||
if len(options.publish) > 0 && options.servicePorts {
|
||||
return fmt.Errorf("--service-ports and --publish are incompatible")
|
||||
}
|
||||
if cmd.Flags().Changed("entrypoint") {
|
||||
command, err := shellwords.Parse(opts.entrypoint)
|
||||
command, err := shellwords.Parse(options.entrypoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts.entrypointCmd = command
|
||||
options.entrypointCmd = command
|
||||
}
|
||||
if cmd.Flags().Changed("tty") {
|
||||
if cmd.Flags().Changed("no-TTY") {
|
||||
return fmt.Errorf("--tty and --no-TTY can't be used together")
|
||||
} else {
|
||||
options.noTty = !options.tty
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
project, err := p.toProject([]string{opts.Service}, cgo.WithResolvedPaths(true))
|
||||
project, err := p.ToProject([]string{options.Service}, cgo.WithResolvedPaths(true), cgo.WithDiscardEnvFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
opts.ignoreOrphans = utils.StringToBool(project.Environment["COMPOSE_IGNORE_ORPHANS"])
|
||||
return runRun(ctx, backend, project, opts, createOpts)
|
||||
|
||||
options.ignoreOrphans = utils.StringToBool(project.Environment[ComposeIgnoreOrphans])
|
||||
return runRun(ctx, backend, project, options, createOpts, streams)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVarP(&opts.Detach, "detach", "d", false, "Run container in background and print container ID")
|
||||
flags.StringArrayVarP(&opts.environment, "env", "e", []string{}, "Set environment variables")
|
||||
flags.StringArrayVarP(&opts.labels, "label", "l", []string{}, "Add or override a label")
|
||||
flags.BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
|
||||
flags.BoolVarP(&opts.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected).")
|
||||
flags.StringVar(&opts.name, "name", "", "Assign a name to the container")
|
||||
flags.StringVarP(&opts.user, "user", "u", "", "Run as specified username or uid")
|
||||
flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
|
||||
flags.StringVar(&opts.entrypoint, "entrypoint", "", "Override the entrypoint of the image")
|
||||
flags.BoolVar(&opts.noDeps, "no-deps", false, "Don't start linked services.")
|
||||
flags.StringArrayVarP(&opts.volumes, "volume", "v", []string{}, "Bind mount a volume.")
|
||||
flags.StringArrayVarP(&opts.publish, "publish", "p", []string{}, "Publish a container's port(s) to the host.")
|
||||
flags.BoolVar(&opts.useAliases, "use-aliases", false, "Use the service's network useAliases in the network(s) the container connects to.")
|
||||
flags.BoolVar(&opts.servicePorts, "service-ports", false, "Run command with the service's ports enabled and mapped to the host.")
|
||||
flags.BoolVar(&opts.quietPull, "quiet-pull", false, "Pull without printing progress information.")
|
||||
flags.BoolVarP(&options.Detach, "detach", "d", false, "Run container in background and print container ID")
|
||||
flags.StringArrayVarP(&options.environment, "env", "e", []string{}, "Set environment variables")
|
||||
flags.StringArrayVarP(&options.labels, "label", "l", []string{}, "Add or override a label")
|
||||
flags.BoolVar(&options.Remove, "rm", false, "Automatically remove the container when it exits")
|
||||
flags.BoolVarP(&options.noTty, "no-TTY", "T", !streams.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected).")
|
||||
flags.StringVar(&options.name, "name", "", "Assign a name to the container")
|
||||
flags.StringVarP(&options.user, "user", "u", "", "Run as specified username or uid")
|
||||
flags.StringVarP(&options.workdir, "workdir", "w", "", "Working directory inside the container")
|
||||
flags.StringVar(&options.entrypoint, "entrypoint", "", "Override the entrypoint of the image")
|
||||
flags.Var(&options.capAdd, "cap-add", "Add Linux capabilities")
|
||||
flags.Var(&options.capDrop, "cap-drop", "Drop Linux capabilities")
|
||||
flags.BoolVar(&options.noDeps, "no-deps", false, "Don't start linked services.")
|
||||
flags.StringArrayVarP(&options.volumes, "volume", "v", []string{}, "Bind mount a volume.")
|
||||
flags.StringArrayVarP(&options.publish, "publish", "p", []string{}, "Publish a container's port(s) to the host.")
|
||||
flags.BoolVar(&options.useAliases, "use-aliases", false, "Use the service's network useAliases in the network(s) the container connects to.")
|
||||
flags.BoolVar(&options.servicePorts, "service-ports", false, "Run command with the service's ports enabled and mapped to the host.")
|
||||
flags.BoolVar(&options.quietPull, "quiet-pull", false, "Pull without printing progress information.")
|
||||
flags.BoolVar(&createOpts.Build, "build", false, "Build image before starting container.")
|
||||
flags.BoolVar(&createOpts.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
|
||||
|
||||
cmd.Flags().BoolVarP(&opts.interactive, "interactive", "i", true, "Keep STDIN open even if not attached.")
|
||||
cmd.Flags().BoolP("tty", "t", true, "Allocate a pseudo-TTY.")
|
||||
cmd.Flags().BoolVarP(&options.interactive, "interactive", "i", true, "Keep STDIN open even if not attached.")
|
||||
cmd.Flags().BoolVarP(&options.tty, "tty", "t", true, "Allocate a pseudo-TTY.")
|
||||
cmd.Flags().MarkHidden("tty") //nolint:errcheck
|
||||
|
||||
flags.SetNormalizeFunc(normalizeRunFlags)
|
||||
@@ -183,23 +197,26 @@ func normalizeRunFlags(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
return pflag.NormalizedName(name)
|
||||
}
|
||||
|
||||
func runRun(ctx context.Context, backend api.Service, project *types.Project, opts runOptions, createOpts createOptions) error {
|
||||
err := opts.apply(project)
|
||||
func runRun(ctx context.Context, backend api.Service, project *types.Project, options runOptions, createOpts createOptions, streams api.Streams) error {
|
||||
err := options.apply(project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
createOpts.Apply(project)
|
||||
err = createOpts.Apply(project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = progress.Run(ctx, func(ctx context.Context) error {
|
||||
return startDependencies(ctx, backend, *project, opts.Service, opts.ignoreOrphans)
|
||||
})
|
||||
return startDependencies(ctx, backend, *project, options.Service, options.ignoreOrphans)
|
||||
}, streams.Err())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
labels := types.Labels{}
|
||||
for _, s := range opts.labels {
|
||||
for _, s := range options.labels {
|
||||
parts := strings.SplitN(s, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("label must be set as KEY=VALUE")
|
||||
@@ -209,27 +226,29 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
|
||||
|
||||
// start container and attach to container streams
|
||||
runOpts := api.RunOptions{
|
||||
Name: opts.name,
|
||||
Service: opts.Service,
|
||||
Command: opts.Command,
|
||||
Detach: opts.Detach,
|
||||
AutoRemove: opts.Remove,
|
||||
Tty: !opts.noTty,
|
||||
Interactive: opts.interactive,
|
||||
WorkingDir: opts.workdir,
|
||||
User: opts.user,
|
||||
Environment: opts.environment,
|
||||
Entrypoint: opts.entrypointCmd,
|
||||
Name: options.name,
|
||||
Service: options.Service,
|
||||
Command: options.Command,
|
||||
Detach: options.Detach,
|
||||
AutoRemove: options.Remove,
|
||||
Tty: !options.noTty,
|
||||
Interactive: options.interactive,
|
||||
WorkingDir: options.workdir,
|
||||
User: options.user,
|
||||
CapAdd: options.capAdd.GetAll(),
|
||||
CapDrop: options.capDrop.GetAll(),
|
||||
Environment: options.environment,
|
||||
Entrypoint: options.entrypointCmd,
|
||||
Labels: labels,
|
||||
UseNetworkAliases: opts.useAliases,
|
||||
NoDeps: opts.noDeps,
|
||||
UseNetworkAliases: options.useAliases,
|
||||
NoDeps: options.noDeps,
|
||||
Index: 0,
|
||||
QuietPull: opts.quietPull,
|
||||
QuietPull: options.quietPull,
|
||||
}
|
||||
|
||||
for i, service := range project.Services {
|
||||
if service.Name == opts.Service {
|
||||
service.StdinOpen = opts.interactive
|
||||
if service.Name == options.Service {
|
||||
service.StdinOpen = options.interactive
|
||||
project.Services[i] = service
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ import (
|
||||
)
|
||||
|
||||
type startOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
}
|
||||
|
||||
func startCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func startCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := startOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
startCmd := &cobra.Command{
|
||||
Use: "start [SERVICE...]",
|
||||
|
||||
@@ -26,14 +26,14 @@ import (
|
||||
)
|
||||
|
||||
type stopOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
timeChanged bool
|
||||
timeout int
|
||||
}
|
||||
|
||||
func stopCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func stopCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := stopOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "stop [OPTIONS] [SERVICE...]",
|
||||
@@ -47,7 +47,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
flags := cmd.Flags()
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
|
||||
flags.IntVarP(&opts.timeout, "timeout", "t", 0, "Specify a shutdown timeout in seconds")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
@@ -31,25 +30,25 @@ import (
|
||||
)
|
||||
|
||||
type topOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
}
|
||||
|
||||
func topCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func topCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
opts := topOptions{
|
||||
projectOptions: p,
|
||||
ProjectOptions: p,
|
||||
}
|
||||
topCmd := &cobra.Command{
|
||||
Use: "top [SERVICES...]",
|
||||
Short: "Display the running processes",
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runTop(ctx, backend, opts, args)
|
||||
return runTop(ctx, streams, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
return topCmd
|
||||
}
|
||||
|
||||
func runTop(ctx context.Context, backend api.Service, opts topOptions, services []string) error {
|
||||
func runTop(ctx context.Context, streams api.Streams, backend api.Service, opts topOptions, services []string) error {
|
||||
projectName, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -64,8 +63,8 @@ func runTop(ctx context.Context, backend api.Service, opts topOptions, services
|
||||
})
|
||||
|
||||
for _, container := range containers {
|
||||
fmt.Printf("%s\n", container.Name)
|
||||
err := psPrinter(os.Stdout, func(w io.Writer) {
|
||||
fmt.Fprintf(streams.Out(), "%s\n", container.Name)
|
||||
err := psPrinter(streams.Out(), func(w io.Writer) {
|
||||
for _, proc := range container.Processes {
|
||||
info := []interface{}{}
|
||||
for _, p := range proc {
|
||||
|
||||
@@ -19,13 +19,10 @@ package compose
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
@@ -34,7 +31,7 @@ import (
|
||||
|
||||
// composeOptions hold options common to `up` and `run` to run compose project
|
||||
type composeOptions struct {
|
||||
*projectOptions
|
||||
*ProjectOptions
|
||||
}
|
||||
|
||||
type upOptions struct {
|
||||
@@ -44,26 +41,22 @@ type upOptions struct {
|
||||
noDeps bool
|
||||
cascadeStop bool
|
||||
exitCodeFrom string
|
||||
scale []string
|
||||
noColor bool
|
||||
noPrefix bool
|
||||
attachDependencies bool
|
||||
attach []string
|
||||
noAttach []string
|
||||
timestamp bool
|
||||
wait bool
|
||||
waitTimeout int
|
||||
}
|
||||
|
||||
func (opts upOptions) apply(project *types.Project, services []string) error {
|
||||
if opts.noDeps {
|
||||
enabled, err := project.GetServices(services...)
|
||||
err := project.ForServices(services, types.IgnoreDependencies)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, s := range project.Services {
|
||||
if !utils.StringContains(services, s.Name) {
|
||||
project.DisabledServices = append(project.DisabledServices, s)
|
||||
}
|
||||
}
|
||||
project.Services = enabled
|
||||
}
|
||||
|
||||
if opts.exitCodeFrom != "" {
|
||||
@@ -73,41 +66,26 @@ func (opts upOptions) apply(project *types.Project, services []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
for _, scale := range opts.scale {
|
||||
split := strings.Split(scale, "=")
|
||||
if len(split) != 2 {
|
||||
return fmt.Errorf("invalid --scale option %q. Should be SERVICE=NUM", scale)
|
||||
}
|
||||
name := split[0]
|
||||
replicas, err := strconv.Atoi(split[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = setServiceScale(project, name, uint64(replicas))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func upCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
func upCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *cobra.Command {
|
||||
up := upOptions{}
|
||||
create := createOptions{}
|
||||
upCmd := &cobra.Command{
|
||||
Use: "up [OPTIONS] [SERVICE...]",
|
||||
Short: "Create and start containers",
|
||||
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
|
||||
create.pullChanged = cmd.Flags().Changed("pull")
|
||||
create.timeChanged = cmd.Flags().Changed("timeout")
|
||||
return validateFlags(&up, &create)
|
||||
}),
|
||||
RunE: p.WithServices(func(ctx context.Context, project *types.Project, services []string) error {
|
||||
create.ignoreOrphans = utils.StringToBool(project.Environment["COMPOSE_IGNORE_ORPHANS"])
|
||||
create.ignoreOrphans = utils.StringToBool(project.Environment[ComposeIgnoreOrphans])
|
||||
if create.ignoreOrphans && create.removeOrphans {
|
||||
return fmt.Errorf("COMPOSE_IGNORE_ORPHANS and --remove-orphans cannot be combined")
|
||||
return fmt.Errorf("%s and --remove-orphans cannot be combined", ComposeIgnoreOrphans)
|
||||
}
|
||||
return runUp(ctx, backend, create, up, project, services)
|
||||
return runUp(ctx, streams, backend, create, up, project, services)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
@@ -117,7 +95,7 @@ func upCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
flags.BoolVar(&create.noBuild, "no-build", false, "Don't build an image, even if it's missing.")
|
||||
flags.StringVar(&create.Pull, "pull", "missing", `Pull image before running ("always"|"missing"|"never")`)
|
||||
flags.BoolVar(&create.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
|
||||
flags.StringArrayVar(&up.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.")
|
||||
flags.StringArrayVar(&create.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.")
|
||||
flags.BoolVar(&up.noColor, "no-color", false, "Produce monochrome output.")
|
||||
flags.BoolVar(&up.noPrefix, "no-log-prefix", false, "Don't print prefix in logs.")
|
||||
flags.BoolVar(&create.forceRecreate, "force-recreate", false, "Recreate containers even if their configuration and image haven't changed.")
|
||||
@@ -125,14 +103,17 @@ func upCommand(p *projectOptions, backend api.Service) *cobra.Command {
|
||||
flags.BoolVar(&up.noStart, "no-start", false, "Don't start the services after creating them.")
|
||||
flags.BoolVar(&up.cascadeStop, "abort-on-container-exit", false, "Stops all containers if any container was stopped. Incompatible with -d")
|
||||
flags.StringVar(&up.exitCodeFrom, "exit-code-from", "", "Return the exit code of the selected service container. Implies --abort-on-container-exit")
|
||||
flags.IntVarP(&create.timeout, "timeout", "t", 10, "Use this timeout in seconds for container shutdown when attached or when containers are already running.")
|
||||
flags.IntVarP(&create.timeout, "timeout", "t", 0, "Use this timeout in seconds for container shutdown when attached or when containers are already running.")
|
||||
flags.BoolVar(&up.timestamp, "timestamps", false, "Show timestamps.")
|
||||
flags.BoolVar(&up.noDeps, "no-deps", false, "Don't start linked services.")
|
||||
flags.BoolVar(&create.recreateDeps, "always-recreate-deps", false, "Recreate dependent containers. Incompatible with --no-recreate.")
|
||||
flags.BoolVarP(&create.noInherit, "renew-anon-volumes", "V", false, "Recreate anonymous volumes instead of retrieving data from the previous containers.")
|
||||
flags.BoolVar(&up.attachDependencies, "attach-dependencies", false, "Attach to dependent containers.")
|
||||
flags.BoolVar(&create.quietPull, "quiet-pull", false, "Pull without printing progress information.")
|
||||
flags.StringArrayVar(&up.attach, "attach", []string{}, "Attach to service output.")
|
||||
flags.StringArrayVar(&up.noAttach, "no-attach", []string{}, "Don't attach to specified service.")
|
||||
flags.BoolVar(&up.wait, "wait", false, "Wait for services to be running|healthy. Implies detached mode.")
|
||||
flags.IntVar(&up.waitTimeout, "wait-timeout", 0, "timeout waiting for application to be running|healthy.")
|
||||
|
||||
return upCmd
|
||||
}
|
||||
@@ -162,33 +143,51 @@ func validateFlags(up *upOptions, create *createOptions) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func runUp(ctx context.Context, backend api.Service, createOptions createOptions, upOptions upOptions, project *types.Project, services []string) error {
|
||||
func runUp(ctx context.Context, streams api.Streams, backend api.Service, createOptions createOptions, upOptions upOptions, project *types.Project, services []string) error {
|
||||
if len(project.Services) == 0 {
|
||||
return fmt.Errorf("no service selected")
|
||||
}
|
||||
|
||||
createOptions.Apply(project)
|
||||
err := createOptions.Apply(project)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := upOptions.apply(project, services)
|
||||
err = upOptions.apply(project, services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var consumer api.LogConsumer
|
||||
if !upOptions.Detach {
|
||||
consumer = formatter.NewLogConsumer(ctx, os.Stdout, !upOptions.noColor, !upOptions.noPrefix)
|
||||
consumer = formatter.NewLogConsumer(ctx, streams.Out(), streams.Err(), !upOptions.noColor, !upOptions.noPrefix, upOptions.timestamp)
|
||||
}
|
||||
|
||||
attachTo := services
|
||||
attachTo := utils.Set[string]{}
|
||||
if len(upOptions.attach) > 0 {
|
||||
attachTo = upOptions.attach
|
||||
attachTo.AddAll(upOptions.attach...)
|
||||
}
|
||||
if upOptions.attachDependencies {
|
||||
attachTo = project.ServiceNames()
|
||||
if err := project.WithServices(attachTo.Elements(), func(s types.ServiceConfig) error {
|
||||
if s.Attach == nil || *s.Attach {
|
||||
attachTo.Add(s.Name)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(attachTo) == 0 {
|
||||
attachTo = project.ServiceNames()
|
||||
if err := project.WithServices(services, func(s types.ServiceConfig) error {
|
||||
if s.Attach == nil || *s.Attach {
|
||||
attachTo.Add(s.Name)
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
attachTo.RemoveAll(upOptions.noAttach...)
|
||||
|
||||
create := api.CreateOptions{
|
||||
Services: services,
|
||||
@@ -205,15 +204,19 @@ func runUp(ctx context.Context, backend api.Service, createOptions createOptions
|
||||
return backend.Create(ctx, project, create)
|
||||
}
|
||||
|
||||
timeout := time.Duration(upOptions.waitTimeout) * time.Second
|
||||
|
||||
return backend.Up(ctx, project, api.UpOptions{
|
||||
Create: create,
|
||||
Start: api.StartOptions{
|
||||
Project: project,
|
||||
Attach: consumer,
|
||||
AttachTo: attachTo,
|
||||
AttachTo: attachTo.Elements(),
|
||||
ExitCodeFrom: upOptions.exitCodeFrom,
|
||||
CascadeStop: upOptions.cascadeStop,
|
||||
Wait: upOptions.wait,
|
||||
WaitTimeout: timeout,
|
||||
Services: services,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ func TestApplyScaleOpt(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
opt := upOptions{scale: []string{"foo=2"}}
|
||||
err := opt.apply(&p, nil)
|
||||
opt := createOptions{scale: []string{"foo=2"}}
|
||||
err := opt.Apply(&p)
|
||||
assert.NilError(t, err)
|
||||
foo, err := p.GetService("foo")
|
||||
assert.NilError(t, err)
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/compose/v2/cmd/formatter"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -32,14 +33,14 @@ type versionOptions struct {
|
||||
short bool
|
||||
}
|
||||
|
||||
func versionCommand() *cobra.Command {
|
||||
func versionCommand(streams command.Cli) *cobra.Command {
|
||||
opts := versionOptions{}
|
||||
cmd := &cobra.Command{
|
||||
Use: "version [OPTIONS]",
|
||||
Short: "Show the Docker Compose version information",
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
runVersion(opts)
|
||||
runVersion(opts, streams)
|
||||
return nil
|
||||
},
|
||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
@@ -56,14 +57,14 @@ func versionCommand() *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runVersion(opts versionOptions) {
|
||||
func runVersion(opts versionOptions, streams command.Cli) {
|
||||
if opts.short {
|
||||
fmt.Println(strings.TrimPrefix(internal.Version, "v"))
|
||||
fmt.Fprintln(streams.Out(), strings.TrimPrefix(internal.Version, "v"))
|
||||
return
|
||||
}
|
||||
if opts.format == formatter.JSON {
|
||||
fmt.Printf("{\"version\":%q}\n", internal.Version)
|
||||
fmt.Fprintf(streams.Out(), "{\"version\":%q}\n", internal.Version)
|
||||
return
|
||||
}
|
||||
fmt.Println("Docker Compose version", internal.Version)
|
||||
fmt.Fprintln(streams.Out(), "Docker Compose version", internal.Version)
|
||||
}
|
||||
|
||||
96
cmd/compose/viz.go
Normal file
96
cmd/compose/viz.go
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright 2023 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type vizOptions struct {
|
||||
*ProjectOptions
|
||||
includeNetworks bool
|
||||
includePorts bool
|
||||
includeImageName bool
|
||||
indentationStr string
|
||||
}
|
||||
|
||||
func vizCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := vizOptions{
|
||||
ProjectOptions: p,
|
||||
}
|
||||
var indentationSize int
|
||||
var useSpaces bool
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "viz [OPTIONS]",
|
||||
Short: "EXPERIMENTAL - Generate a graphviz graph from your compose file",
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
var err error
|
||||
opts.indentationStr, err = preferredIndentationStr(indentationSize, useSpaces)
|
||||
return err
|
||||
}),
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runViz(ctx, backend, &opts)
|
||||
}),
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&opts.includePorts, "ports", false, "Include service's exposed ports in output graph")
|
||||
cmd.Flags().BoolVar(&opts.includeNetworks, "networks", false, "Include service's attached networks in output graph")
|
||||
cmd.Flags().BoolVar(&opts.includeImageName, "image", false, "Include service's image name in output graph")
|
||||
cmd.Flags().IntVar(&indentationSize, "indentation-size", 1, "Number of tabs or spaces to use for indentation")
|
||||
cmd.Flags().BoolVar(&useSpaces, "spaces", false, "If given, space character ' ' will be used to indent,\notherwise tab character '\\t' will be used")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runViz(ctx context.Context, backend api.Service, opts *vizOptions) error {
|
||||
_, _ = fmt.Fprintln(os.Stderr, "viz command is EXPERIMENTAL")
|
||||
project, err := opts.ToProject(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// build graph
|
||||
graphStr, _ := backend.Viz(ctx, project, api.VizOptions{
|
||||
IncludeNetworks: opts.includeNetworks,
|
||||
IncludePorts: opts.includePorts,
|
||||
IncludeImageName: opts.includeImageName,
|
||||
Indentation: opts.indentationStr,
|
||||
})
|
||||
|
||||
fmt.Println(graphStr)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// preferredIndentationStr returns a single string given the indentation preference
|
||||
func preferredIndentationStr(size int, useSpace bool) (string, error) {
|
||||
if size < 0 {
|
||||
return "", fmt.Errorf("invalid indentation size: %d", size)
|
||||
}
|
||||
|
||||
indentationStr := "\t"
|
||||
if useSpace {
|
||||
indentationStr = " "
|
||||
}
|
||||
return strings.Repeat(indentationStr, size), nil
|
||||
}
|
||||
92
cmd/compose/viz_test.go
Normal file
92
cmd/compose/viz_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPreferredIndentationStr(t *testing.T) {
|
||||
type args struct {
|
||||
size int
|
||||
useSpace bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "should return '\\t\\t'",
|
||||
args: args{
|
||||
size: 2,
|
||||
useSpace: false,
|
||||
},
|
||||
want: "\t\t",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "should return ' '",
|
||||
args: args{
|
||||
size: 4,
|
||||
useSpace: true,
|
||||
},
|
||||
want: " ",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "should return ''",
|
||||
args: args{
|
||||
size: 0,
|
||||
useSpace: false,
|
||||
},
|
||||
want: "",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "should return ''",
|
||||
args: args{
|
||||
size: 0,
|
||||
useSpace: true,
|
||||
},
|
||||
want: "",
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "should throw error because indentation size < 0",
|
||||
args: args{
|
||||
size: -1,
|
||||
useSpace: false,
|
||||
},
|
||||
want: "",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := preferredIndentationStr(tt.args.size, tt.args.useSpace)
|
||||
if tt.wantErr && assert.NotNilf(t, err, fmt.Sprintf("preferredIndentationStr(%v, %v)", tt.args.size, tt.args.useSpace)) {
|
||||
return
|
||||
}
|
||||
assert.Equalf(t, tt.want, got, "preferredIndentationStr(%v, %v)", tt.args.size, tt.args.useSpace)
|
||||
})
|
||||
}
|
||||
}
|
||||
72
cmd/compose/wait.go
Normal file
72
cmd/compose/wait.go
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright 2023 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type waitOptions struct {
|
||||
*ProjectOptions
|
||||
|
||||
services []string
|
||||
|
||||
downProject bool
|
||||
}
|
||||
|
||||
func waitCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := waitOptions{
|
||||
ProjectOptions: p,
|
||||
}
|
||||
|
||||
var statusCode int64
|
||||
var err error
|
||||
cmd := &cobra.Command{
|
||||
Use: "wait SERVICE [SERVICE...] [OPTIONS]",
|
||||
Short: "Block until the first service container stops",
|
||||
Args: cli.RequiresMinArgs(1),
|
||||
RunE: Adapt(func(ctx context.Context, services []string) error {
|
||||
opts.services = services
|
||||
statusCode, err = runWait(ctx, backend, &opts)
|
||||
return err
|
||||
}),
|
||||
PostRun: func(cmd *cobra.Command, args []string) {
|
||||
os.Exit(int(statusCode))
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&opts.downProject, "down-project", false, "Drops project when the first container stops")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runWait(ctx context.Context, backend api.Service, opts *waitOptions) (int64, error) {
|
||||
_, name, err := opts.projectOrName()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return backend.Wait(ctx, name, api.WaitOptions{
|
||||
Services: opts.services,
|
||||
DownProjectOnContainerExit: opts.downProject,
|
||||
})
|
||||
}
|
||||
61
cmd/compose/watch.go
Normal file
61
cmd/compose/watch.go
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2020 Docker Compose CLI authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package compose
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type watchOptions struct {
|
||||
*ProjectOptions
|
||||
quiet bool
|
||||
}
|
||||
|
||||
func watchCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
|
||||
opts := watchOptions{
|
||||
ProjectOptions: p,
|
||||
}
|
||||
cmd := &cobra.Command{
|
||||
Use: "watch [SERVICE...]",
|
||||
Short: "EXPERIMENTAL - Watch build context for service and rebuild/refresh containers when files are updated",
|
||||
PreRunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return nil
|
||||
}),
|
||||
RunE: Adapt(func(ctx context.Context, args []string) error {
|
||||
return runWatch(ctx, backend, opts, args)
|
||||
}),
|
||||
ValidArgsFunction: completeServiceNames(p),
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&opts.quiet, "quiet", false, "hide build output")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runWatch(ctx context.Context, backend api.Service, opts watchOptions, services []string) error {
|
||||
fmt.Fprintln(os.Stderr, "watch command is EXPERIMENTAL")
|
||||
project, err := opts.ToProject(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return backend.Watch(ctx, project, services, api.WatchOptions{})
|
||||
}
|
||||
@@ -18,10 +18,10 @@ package formatter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
)
|
||||
|
||||
var names = []string{
|
||||
@@ -47,20 +47,20 @@ const (
|
||||
)
|
||||
|
||||
// SetANSIMode configure formatter for colored output on ANSI-compliant console
|
||||
func SetANSIMode(ansi string) {
|
||||
if !useAnsi(ansi) {
|
||||
func SetANSIMode(streams api.Streams, ansi string) {
|
||||
if !useAnsi(streams, ansi) {
|
||||
nextColor = func() colorFunc {
|
||||
return monochrome
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func useAnsi(ansi string) bool {
|
||||
func useAnsi(streams api.Streams, ansi string) bool {
|
||||
switch ansi {
|
||||
case Always:
|
||||
return true
|
||||
case Auto:
|
||||
return isatty.IsTerminal(os.Stdout.Fd())
|
||||
return streams.Out().IsTerminal()
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -87,38 +87,34 @@ func makeColorFunc(code string) colorFunc {
|
||||
}
|
||||
|
||||
var nextColor = rainbowColor
|
||||
var rainbow []colorFunc
|
||||
var currentIndex = 0
|
||||
var mutex sync.Mutex
|
||||
|
||||
func rainbowColor() colorFunc {
|
||||
return <-loop
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
result := rainbow[currentIndex]
|
||||
currentIndex = (currentIndex + 1) % len(rainbow)
|
||||
return result
|
||||
}
|
||||
|
||||
var loop = make(chan colorFunc)
|
||||
|
||||
func init() {
|
||||
colors := map[string]colorFunc{}
|
||||
for i, name := range names {
|
||||
colors[name] = makeColorFunc(strconv.Itoa(30 + i))
|
||||
colors["intense_"+name] = makeColorFunc(strconv.Itoa(30+i) + ";1")
|
||||
}
|
||||
|
||||
go func() {
|
||||
i := 0
|
||||
rainbow := []colorFunc{
|
||||
colors["cyan"],
|
||||
colors["yellow"],
|
||||
colors["green"],
|
||||
colors["magenta"],
|
||||
colors["blue"],
|
||||
colors["intense_cyan"],
|
||||
colors["intense_yellow"],
|
||||
colors["intense_green"],
|
||||
colors["intense_magenta"],
|
||||
colors["intense_blue"],
|
||||
}
|
||||
|
||||
for {
|
||||
loop <- rainbow[i]
|
||||
i = (i + 1) % len(rainbow)
|
||||
}
|
||||
}()
|
||||
rainbow = []colorFunc{
|
||||
colors["cyan"],
|
||||
colors["yellow"],
|
||||
colors["green"],
|
||||
colors["magenta"],
|
||||
colors["blue"],
|
||||
colors["intense_cyan"],
|
||||
colors["intense_yellow"],
|
||||
colors["intense_green"],
|
||||
colors["intense_magenta"],
|
||||
colors["intense_blue"],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,13 @@
|
||||
package formatter
|
||||
|
||||
const (
|
||||
// JSON is the constant for Json formats on list commands
|
||||
// JSON Print in JSON format
|
||||
JSON = "json"
|
||||
// TemplateLegacyJSON the legacy json formatting value using go template
|
||||
TemplateLegacyJSON = "{{json.}}"
|
||||
// PRETTY is the constant for default formats on list commands
|
||||
// Deprecated: use TABLE
|
||||
PRETTY = "pretty"
|
||||
// TABLE Print output in table format with column headers (default)
|
||||
TABLE = "table"
|
||||
)
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
// Print prints formatted lists in different formats
|
||||
func Print(toJSON interface{}, format string, outWriter io.Writer, writerFn func(w io.Writer), headers ...string) error {
|
||||
switch strings.ToLower(format) {
|
||||
case PRETTY, "":
|
||||
case TABLE, PRETTY, "":
|
||||
return PrintPrettySection(outWriter, writerFn, headers...)
|
||||
case TemplateLegacyJSON:
|
||||
switch reflect.TypeOf(toJSON).Kind() {
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"go.uber.org/goleak"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
@@ -71,3 +72,7 @@ func TestPrint(t *testing.T) {
|
||||
{"Name":"myName2","Status":"myStatus2"}
|
||||
`)
|
||||
}
|
||||
|
||||
func TestColorsGoroutinesLeak(t *testing.T) {
|
||||
goleak.VerifyNone(t)
|
||||
}
|
||||
|
||||
@@ -23,8 +23,10 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
)
|
||||
|
||||
// LogConsumer consume logs from services and format them
|
||||
@@ -32,20 +34,24 @@ type logConsumer struct {
|
||||
ctx context.Context
|
||||
presenters sync.Map // map[string]*presenter
|
||||
width int
|
||||
writer io.Writer
|
||||
stdout io.Writer
|
||||
stderr io.Writer
|
||||
color bool
|
||||
prefix bool
|
||||
timestamp bool
|
||||
}
|
||||
|
||||
// NewLogConsumer creates a new LogConsumer
|
||||
func NewLogConsumer(ctx context.Context, w io.Writer, color bool, prefix bool) api.LogConsumer {
|
||||
func NewLogConsumer(ctx context.Context, stdout, stderr io.Writer, color, prefix, timestamp bool) api.LogConsumer {
|
||||
return &logConsumer{
|
||||
ctx: ctx,
|
||||
presenters: sync.Map{},
|
||||
width: 0,
|
||||
writer: w,
|
||||
stdout: stdout,
|
||||
stderr: stderr,
|
||||
color: color,
|
||||
prefix: prefix,
|
||||
timestamp: timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,20 +89,34 @@ func (l *logConsumer) getPresenter(container string) *presenter {
|
||||
}
|
||||
|
||||
// Log formats a log message as received from name/container
|
||||
func (l *logConsumer) Log(container, service, message string) {
|
||||
func (l *logConsumer) Log(container, message string) {
|
||||
l.write(l.stdout, container, message)
|
||||
}
|
||||
|
||||
// Log formats a log message as received from name/container
|
||||
func (l *logConsumer) Err(container, message string) {
|
||||
l.write(l.stderr, container, message)
|
||||
}
|
||||
|
||||
func (l *logConsumer) write(w io.Writer, container, message string) {
|
||||
if l.ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
p := l.getPresenter(container)
|
||||
timestamp := time.Now().Format(jsonmessage.RFC3339NanoFixed)
|
||||
for _, line := range strings.Split(message, "\n") {
|
||||
fmt.Fprintf(l.writer, "%s%s\n", p.prefix, line)
|
||||
if l.timestamp {
|
||||
fmt.Fprintf(w, "%s%s%s\n", p.prefix, timestamp, line)
|
||||
} else {
|
||||
fmt.Fprintf(w, "%s%s\n", p.prefix, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *logConsumer) Status(container, msg string) {
|
||||
p := l.getPresenter(container)
|
||||
s := p.colors(fmt.Sprintf("%s %s\n", container, msg))
|
||||
l.writer.Write([]byte(s)) //nolint:errcheck
|
||||
l.stdout.Write([]byte(s)) //nolint:errcheck
|
||||
}
|
||||
|
||||
func (l *logConsumer) computeWidth() {
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/docker/cli/cli-plugins/manager"
|
||||
"github.com/docker/cli/cli-plugins/plugin"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/compose/v2/cmd/cmdtrace"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/docker/compose/v2/cmd/compatibility"
|
||||
@@ -38,14 +39,20 @@ func pluginMain() {
|
||||
cmd := commands.RootCommand(dockerCli, serviceProxy)
|
||||
originalPreRun := cmd.PersistentPreRunE
|
||||
cmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
|
||||
// initialize the dockerCli instance
|
||||
if err := plugin.PersistentPreRunE(cmd, args); err != nil {
|
||||
return err
|
||||
}
|
||||
// TODO(milas): add an env var to enable logging from the
|
||||
// OTel components for debugging purposes
|
||||
_ = cmdtrace.Setup(cmd, dockerCli)
|
||||
|
||||
if originalPreRun != nil {
|
||||
return originalPreRun(cmd, args)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd.SetFlagErrorFunc(func(c *cobra.Command, err error) error {
|
||||
return dockercli.StatusError{
|
||||
StatusCode: compose.CommandSyntaxFailure.ExitCode,
|
||||
|
||||
21
codecov.yml
Normal file
21
codecov.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
informational: true
|
||||
target: auto
|
||||
threshold: 2%
|
||||
patch:
|
||||
default:
|
||||
informational: true
|
||||
|
||||
comment:
|
||||
require_changes: true
|
||||
|
||||
ignore:
|
||||
- "packaging"
|
||||
- "docs"
|
||||
- "bin"
|
||||
- "e2e"
|
||||
- "pkg/e2e"
|
||||
- "**/*_test.go"
|
||||
@@ -13,26 +13,33 @@
|
||||
// limitations under the License.
|
||||
|
||||
variable "GO_VERSION" {
|
||||
default = "1.19.3"
|
||||
# default ARG value set in Dockerfile
|
||||
default = null
|
||||
}
|
||||
|
||||
variable "BUILD_TAGS" {
|
||||
default = "e2e,kube"
|
||||
default = "e2e"
|
||||
}
|
||||
|
||||
variable "DOCS_FORMATS" {
|
||||
default = "md,yaml"
|
||||
}
|
||||
|
||||
# Defines the output folder
|
||||
# Defines the output folder to override the default behavior.
|
||||
# See Makefile for details, this is generally only useful for
|
||||
# the packaging scripts and care should be taken to not break
|
||||
# them.
|
||||
variable "DESTDIR" {
|
||||
default = ""
|
||||
}
|
||||
function "bindir" {
|
||||
function "outdir" {
|
||||
params = [defaultdir]
|
||||
result = DESTDIR != "" ? DESTDIR : "./bin/${defaultdir}"
|
||||
result = DESTDIR != "" ? DESTDIR : "${defaultdir}"
|
||||
}
|
||||
|
||||
# Special target: https://github.com/docker/metadata-action#bake-definition
|
||||
target "meta-helper" {}
|
||||
|
||||
target "_common" {
|
||||
args = {
|
||||
GO_VERSION = GO_VERSION
|
||||
@@ -71,13 +78,7 @@ target "vendor-validate" {
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "modules-validate" {
|
||||
inherits = ["_common"]
|
||||
target = "modules-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "vendor" {
|
||||
target "vendor-update" {
|
||||
inherits = ["_common"]
|
||||
target = "vendor-update"
|
||||
output = ["."]
|
||||
@@ -86,13 +87,23 @@ target "vendor" {
|
||||
target "test" {
|
||||
inherits = ["_common"]
|
||||
target = "test-coverage"
|
||||
output = [bindir("coverage")]
|
||||
output = [outdir("./bin/coverage/unit")]
|
||||
}
|
||||
|
||||
target "binary-with-coverage" {
|
||||
inherits = ["_common"]
|
||||
target = "binary"
|
||||
args = {
|
||||
BUILD_FLAGS = "-cover -covermode=atomic"
|
||||
}
|
||||
output = [outdir("./bin/build")]
|
||||
platforms = ["local"]
|
||||
}
|
||||
|
||||
target "binary" {
|
||||
inherits = ["_common"]
|
||||
target = "binary"
|
||||
output = [bindir("build")]
|
||||
output = [outdir("./bin/build")]
|
||||
platforms = ["local"]
|
||||
}
|
||||
|
||||
@@ -116,7 +127,7 @@ target "binary-cross" {
|
||||
target "release" {
|
||||
inherits = ["binary-cross"]
|
||||
target = "release"
|
||||
output = [bindir("release")]
|
||||
output = [outdir("./bin/release")]
|
||||
}
|
||||
|
||||
target "docs-validate" {
|
||||
@@ -130,3 +141,8 @@ target "docs-update" {
|
||||
target = "docs-update"
|
||||
output = ["./docs"]
|
||||
}
|
||||
|
||||
target "image-cross" {
|
||||
inherits = ["meta-helper", "binary-cross"]
|
||||
output = ["type=image"]
|
||||
}
|
||||
|
||||
@@ -1,51 +1,54 @@
|
||||
# docker compose
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Docker Compose
|
||||
Define and run multi-container applications with Docker.
|
||||
|
||||
### Subcommands
|
||||
|
||||
| Name | Description |
|
||||
| --- | --- |
|
||||
| [`build`](compose_build.md) | Build or rebuild services |
|
||||
| [`convert`](compose_convert.md) | Converts the compose file to platform's canonical format |
|
||||
| [`cp`](compose_cp.md) | Copy files/folders between a service container and the local filesystem |
|
||||
| [`create`](compose_create.md) | Creates containers for a service. |
|
||||
| [`down`](compose_down.md) | Stop and remove containers, networks |
|
||||
| [`events`](compose_events.md) | Receive real time events from containers. |
|
||||
| [`exec`](compose_exec.md) | Execute a command in a running container. |
|
||||
| [`images`](compose_images.md) | List images used by the created containers |
|
||||
| [`kill`](compose_kill.md) | Force stop service containers. |
|
||||
| [`logs`](compose_logs.md) | View output from containers |
|
||||
| [`ls`](compose_ls.md) | List running compose projects |
|
||||
| [`pause`](compose_pause.md) | Pause services |
|
||||
| [`port`](compose_port.md) | Print the public port for a port binding. |
|
||||
| [`ps`](compose_ps.md) | List containers |
|
||||
| [`pull`](compose_pull.md) | Pull service images |
|
||||
| [`push`](compose_push.md) | Push service images |
|
||||
| [`restart`](compose_restart.md) | Restart service containers |
|
||||
| [`rm`](compose_rm.md) | Removes stopped service containers |
|
||||
| [`run`](compose_run.md) | Run a one-off command on a service. |
|
||||
| [`start`](compose_start.md) | Start services |
|
||||
| [`stop`](compose_stop.md) | Stop services |
|
||||
| [`top`](compose_top.md) | Display the running processes |
|
||||
| [`unpause`](compose_unpause.md) | Unpause services |
|
||||
| [`up`](compose_up.md) | Create and start containers |
|
||||
| [`version`](compose_version.md) | Show the Docker Compose version information |
|
||||
| Name | Description |
|
||||
|:--------------------------------|:------------------------------------------------------------------------|
|
||||
| [`build`](compose_build.md) | Build or rebuild services |
|
||||
| [`config`](compose_config.md) | Parse, resolve and render compose file in canonical format |
|
||||
| [`cp`](compose_cp.md) | Copy files/folders between a service container and the local filesystem |
|
||||
| [`create`](compose_create.md) | Creates containers for a service. |
|
||||
| [`down`](compose_down.md) | Stop and remove containers, networks |
|
||||
| [`events`](compose_events.md) | Receive real time events from containers. |
|
||||
| [`exec`](compose_exec.md) | Execute a command in a running container. |
|
||||
| [`images`](compose_images.md) | List images used by the created containers |
|
||||
| [`kill`](compose_kill.md) | Force stop service containers. |
|
||||
| [`logs`](compose_logs.md) | View output from containers |
|
||||
| [`ls`](compose_ls.md) | List running compose projects |
|
||||
| [`pause`](compose_pause.md) | Pause services |
|
||||
| [`port`](compose_port.md) | Print the public port for a port binding. |
|
||||
| [`ps`](compose_ps.md) | List containers |
|
||||
| [`pull`](compose_pull.md) | Pull service images |
|
||||
| [`push`](compose_push.md) | Push service images |
|
||||
| [`restart`](compose_restart.md) | Restart service containers |
|
||||
| [`rm`](compose_rm.md) | Removes stopped service containers |
|
||||
| [`run`](compose_run.md) | Run a one-off command on a service. |
|
||||
| [`start`](compose_start.md) | Start services |
|
||||
| [`stop`](compose_stop.md) | Stop services |
|
||||
| [`top`](compose_top.md) | Display the running processes |
|
||||
| [`unpause`](compose_unpause.md) | Unpause services |
|
||||
| [`up`](compose_up.md) | Create and start containers |
|
||||
| [`version`](compose_version.md) | Show the Docker Compose version information |
|
||||
| [`wait`](compose_wait.md) | Block until the first service container stops |
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--ansi` | `string` | `auto` | Control when to print ANSI control characters ("never"\|"always"\|"auto") |
|
||||
| `--compatibility` | | | Run compose in backward compatibility mode |
|
||||
| `--env-file` | `string` | | Specify an alternate environment file. |
|
||||
| `-f`, `--file` | `stringArray` | | Compose configuration files |
|
||||
| `--profile` | `stringArray` | | Specify a profile to enable |
|
||||
| `--project-directory` | `string` | | Specify an alternate working directory
|
||||
(default: the path of the, first specified, Compose file) |
|
||||
| `-p`, `--project-name` | `string` | | Project name |
|
||||
| Name | Type | Default | Description |
|
||||
|:-----------------------|:--------------|:--------|:----------------------------------------------------------------------------------------------------|
|
||||
| `--ansi` | `string` | `auto` | Control when to print ANSI control characters ("never"\|"always"\|"auto") |
|
||||
| `--compatibility` | | | Run compose in backward compatibility mode |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--env-file` | `stringArray` | | Specify an alternate environment file. |
|
||||
| `-f`, `--file` | `stringArray` | | Compose configuration files |
|
||||
| `--parallel` | `int` | `-1` | Control max parallelism, -1 for unlimited |
|
||||
| `--profile` | `stringArray` | | Specify a profile to enable |
|
||||
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
|
||||
| `--project-directory` | `string` | | Specify an alternate working directory<br>(default: the path of the, first specified, Compose file) |
|
||||
| `-p`, `--project-name` | `string` | | Project name |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
@@ -114,12 +117,19 @@ $ docker compose -f ~/sandbox/rails/compose.yaml pull db
|
||||
|
||||
### Use `-p` to specify a project name
|
||||
|
||||
Each configuration has a project name. If you supply a `-p` flag, you can specify a project name. If you don’t
|
||||
specify the flag, Compose uses the current directory name.
|
||||
Project name can also be set by `COMPOSE_PROJECT_NAME` environment variable.
|
||||
|
||||
Many Compose subcommands can be run without a Compose file by passing
|
||||
the project name.
|
||||
Each configuration has a project name. Compose sets the project name using
|
||||
the following mechanisms, in order of precedence:
|
||||
- The `-p` command line flag
|
||||
- The `COMPOSE_PROJECT_NAME` environment variable
|
||||
- The top level `name:` variable from the config file (or the last `name:`
|
||||
from a series of config files specified using `-f`)
|
||||
- The `basename` of the project directory containing the config file (or
|
||||
containing the first config file specified using `-f`)
|
||||
- The `basename` of the current directory if no config file is specified
|
||||
Project names must contain only lowercase letters, decimal digits, dashes,
|
||||
and underscores, and must begin with a lowercase letter or decimal digit. If
|
||||
the `basename` of the project directory or current directory violates this
|
||||
constraint, you must use one of the other mechanisms.
|
||||
|
||||
```console
|
||||
$ docker compose -p my_project ps -a
|
||||
@@ -140,15 +150,49 @@ You can also enable multiple profiles, e.g. with `docker compose --profile front
|
||||
|
||||
Profiles can also be set by `COMPOSE_PROFILES` environment variable.
|
||||
|
||||
### Configuring parallelism
|
||||
|
||||
Use `--parallel` to specify the maximum level of parallelism for concurrent engine calls.
|
||||
Calling `docker compose --parallel 1 pull` will pull the pullable images defined in the Compose file
|
||||
one at a time. This can also be used to control build concurrency.
|
||||
|
||||
Parallelism can also be set by the `COMPOSE_PARALLEL_LIMIT` environment variable.
|
||||
|
||||
### Set up environment variables
|
||||
|
||||
You can set environment variables for various docker compose options, including the `-f`, `-p` and `--profiles` flags.
|
||||
|
||||
Setting the `COMPOSE_FILE` environment variable is equivalent to passing the `-f` flag,
|
||||
`COMPOSE_PROJECT_NAME` environment variable does the same as the `-p` flag,
|
||||
and `COMPOSE_PROFILES` environment variable is equivalent to the `--profiles` flag.
|
||||
`COMPOSE_PROFILES` environment variable is equivalent to the `--profiles` flag
|
||||
and `COMPOSE_PARALLEL_LIMIT` does the same as the `--parallel` flag.
|
||||
|
||||
If flags are explicitly set on the command line, the associated environment variable is ignored.
|
||||
|
||||
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
|
||||
containers for the project.
|
||||
|
||||
### Use Dry Run mode to test your command
|
||||
|
||||
Use `--dry-run` flag to test a command without changing your application stack state.
|
||||
Dry Run mode shows you all the steps Compose applies when executing a command, for example:
|
||||
```console
|
||||
$ docker compose --dry-run up --build -d
|
||||
[+] Pulling 1/1
|
||||
✔ DRY-RUN MODE - db Pulled 0.9s
|
||||
[+] Running 10/8
|
||||
✔ DRY-RUN MODE - build service backend 0.0s
|
||||
✔ DRY-RUN MODE - ==> ==> writing image dryRun-754a08ddf8bcb1cf22f310f09206dd783d42f7dd 0.0s
|
||||
✔ DRY-RUN MODE - ==> ==> naming to nginx-golang-mysql-backend 0.0s
|
||||
✔ DRY-RUN MODE - Network nginx-golang-mysql_default Created 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-db-1 Created 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-backend-1 Created 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-proxy-1 Created 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-db-1 Healthy 0.5s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-backend-1 Started 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-proxy-1 Started Started
|
||||
```
|
||||
From the example above, you can see that the first step is to pull the image defined by `db` service, then build the `backend` service.
|
||||
Next, the containers are created. The `db` service is started, and the `backend` and `proxy` wait until the `db` service is healthy before starting.
|
||||
|
||||
Dry Run mode works with almost all commands. You cannot use Dry Run mode with a command that doesn't change the state of a Compose stack such as `ps`, `ls`, `logs` for example.
|
||||
|
||||
22
docs/reference/compose_alpha.md
Normal file
22
docs/reference/compose_alpha.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# docker compose alpha
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Experimental commands
|
||||
|
||||
### Subcommands
|
||||
|
||||
| Name | Description |
|
||||
|:----------------------------------|:-----------------------------------------------------------------------------------------------------|
|
||||
| [`viz`](compose_alpha_viz.md) | EXPERIMENTAL - Generate a graphviz graph from your compose file |
|
||||
| [`watch`](compose_alpha_watch.md) | EXPERIMENTAL - Watch build context for service and rebuild/refresh containers when files are updated |
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:------------|:-----|:--------|:--------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
8
docs/reference/compose_alpha_dry-run.md
Normal file
8
docs/reference/compose_alpha_dry-run.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# docker compose alpha dry-run
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
EXPERIMENTAL - Dry run command allow you to test a command without applying changes
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
14
docs/reference/compose_alpha_publish.md
Normal file
14
docs/reference/compose_alpha_publish.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# docker compose alpha publish
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Publish compose application
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:------------|:-----|:--------|:--------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
19
docs/reference/compose_alpha_viz.md
Normal file
19
docs/reference/compose_alpha_viz.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# docker compose alpha viz
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
EXPERIMENTAL - Generate a graphviz graph from your compose file
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------|:------|:--------|:---------------------------------------------------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--image` | | | Include service's image name in output graph |
|
||||
| `--indentation-size` | `int` | `1` | Number of tabs or spaces to use for indentation |
|
||||
| `--networks` | | | Include service's attached networks in output graph |
|
||||
| `--ports` | | | Include service's exposed ports in output graph |
|
||||
| `--spaces` | | | If given, space character ' ' will be used to indent,<br>otherwise tab character '\t' will be used |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
15
docs/reference/compose_alpha_watch.md
Normal file
15
docs/reference/compose_alpha_watch.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# docker compose alpha watch
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
EXPERIMENTAL - Watch build context for service and rebuild/refresh containers when files are updated
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:------------|:-----|:--------|:--------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--quiet` | | | hide build output |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,14 +5,17 @@ Build or rebuild services
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--build-arg` | `stringArray` | | Set build-time variables for services. |
|
||||
| `--no-cache` | | | Do not use cache when building the image |
|
||||
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
|
||||
| `--pull` | | | Always attempt to pull a newer version of the image. |
|
||||
| `-q`, `--quiet` | | | Don't print anything to STDOUT |
|
||||
| `--ssh` | `string` | | Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent) |
|
||||
| Name | Type | Default | Description |
|
||||
|:-----------------|:--------------|:--------|:------------------------------------------------------------------------------------------------------------|
|
||||
| `--build-arg` | `stringArray` | | Set build-time variables for services. |
|
||||
| `--builder` | `string` | | Set builder to use. |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `-m`, `--memory` | `bytes` | `0` | Set memory limit for the build container. Not supported by BuildKit. |
|
||||
| `--no-cache` | | | Do not use cache when building the image |
|
||||
| `--pull` | | | Always attempt to pull a newer version of the image. |
|
||||
| `--push` | | | Push service images. |
|
||||
| `-q`, `--quiet` | | | Don't print anything to STDOUT |
|
||||
| `--ssh` | `string` | | Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent) |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
36
docs/reference/compose_config.md
Normal file
36
docs/reference/compose_config.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# docker compose convert
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Parse, resolve and render compose file in canonical format
|
||||
|
||||
### Aliases
|
||||
|
||||
`docker compose config`, `docker compose convert`
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:--------------------------|:---------|:--------|:----------------------------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--format` | `string` | `yaml` | Format the output. Values: [yaml \| json] |
|
||||
| `--hash` | `string` | | Print the service config hash, one per line. |
|
||||
| `--images` | | | Print the image names, one per line. |
|
||||
| `--no-consistency` | | | Don't check model consistency - warning: may produce invalid Compose output |
|
||||
| `--no-interpolate` | | | Don't interpolate environment variables. |
|
||||
| `--no-normalize` | | | Don't normalize compose model. |
|
||||
| `--no-path-resolution` | | | Don't resolve file paths. |
|
||||
| `-o`, `--output` | `string` | | Save to file (default to stdout) |
|
||||
| `--profiles` | | | Print the profile names, one per line. |
|
||||
| `-q`, `--quiet` | | | Only validate the configuration, don't print anything. |
|
||||
| `--resolve-image-digests` | | | Pin image tags to digests. |
|
||||
| `--services` | | | Print the service names, one per line. |
|
||||
| `--volumes` | | | Print the volume names, one per line. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
`docker compose config` renders the actual data model to be applied on the Docker engine.
|
||||
it merges the Compose files set by `-f` flags, resolves variables in the Compose file, and expands short-notation into
|
||||
the canonical format.
|
||||
@@ -1,36 +0,0 @@
|
||||
# docker compose convert
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Converts the compose file to platform's canonical format
|
||||
|
||||
### Aliases
|
||||
|
||||
`docker compose convert`, `docker compose config`
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--format` | `string` | `yaml` | Format the output. Values: [yaml \| json] |
|
||||
| `--hash` | `string` | | Print the service config hash, one per line. |
|
||||
| `--images` | | | Print the image names, one per line. |
|
||||
| `--no-consistency` | | | Don't check model consistency - warning: may produce invalid Compose output |
|
||||
| `--no-interpolate` | | | Don't interpolate environment variables. |
|
||||
| `--no-normalize` | | | Don't normalize compose model. |
|
||||
| `-o`, `--output` | `string` | | Save to file (default to stdout) |
|
||||
| `--profiles` | | | Print the profile names, one per line. |
|
||||
| `-q`, `--quiet` | | | Only validate the configuration, don't print anything. |
|
||||
| `--resolve-image-digests` | | | Pin image tags to digests. |
|
||||
| `--services` | | | Print the service names, one per line. |
|
||||
| `--volumes` | | | Print the volume names, one per line. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
## Description
|
||||
|
||||
`docker compose convert` renders the actual data model to be applied on the target platform. When used with the Docker engine,
|
||||
it merges the Compose files set by `-f` flags, resolves variables in the Compose file, and expands short-notation into
|
||||
the canonical format.
|
||||
|
||||
To allow smooth migration from docker-compose, this subcommand declares alias `docker compose config`
|
||||
@@ -5,11 +5,12 @@ Copy files/folders between a service container and the local filesystem
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-a`, `--archive` | | | Archive mode (copy all uid/gid information) |
|
||||
| `-L`, `--follow-link` | | | Always follow symbol link in SRC_PATH |
|
||||
| `--index` | `int` | `0` | Index of the container if there are multiple instances of a service . |
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------------|:------|:--------|:--------------------------------------------------------|
|
||||
| `-a`, `--archive` | | | Archive mode (copy all uid/gid information) |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `-L`, `--follow-link` | | | Always follow symbol link in SRC_PATH |
|
||||
| `--index` | `int` | `0` | index of the container if service has multiple replicas |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,13 +5,16 @@ Creates containers for a service.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--build` | | | Build images before starting containers. |
|
||||
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed. |
|
||||
| `--no-build` | | | Don't build an image, even if it's missing. |
|
||||
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
|
||||
| `--pull` | `string` | `missing` | Pull image before running ("always"\|"missing"\|"never") |
|
||||
| Name | Type | Default | Description |
|
||||
|:-------------------|:--------------|:----------|:----------------------------------------------------------------------------------------------|
|
||||
| `--build` | | | Build images before starting containers. |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed. |
|
||||
| `--no-build` | | | Don't build an image, even if it's missing. |
|
||||
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
|
||||
| `--pull` | `string` | `missing` | Pull image before running ("always"\|"missing"\|"never") |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,12 +5,13 @@ Stop and remove containers, networks
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `--rmi` | `string` | | Remove images used by services. "local" remove only images that don't have a custom tag ("local"\|"all") |
|
||||
| `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds |
|
||||
| `-v`, `--volumes` | | | Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. |
|
||||
| Name | Type | Default | Description |
|
||||
|:-------------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `--rmi` | `string` | | Remove images used by services. "local" remove only images that don't have a custom tag ("local"\|"all") |
|
||||
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |
|
||||
| `-v`, `--volumes` | | | Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,9 +5,10 @@ Receive real time events from containers.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--json` | | | Output events as a stream of json objects |
|
||||
| Name | Type | Default | Description |
|
||||
|:------------|:-----|:--------|:------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--json` | | | Output events as a stream of json objects |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,15 +5,16 @@ Execute a command in a running container.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-d`, `--detach` | | | Detached mode: Run command in the background. |
|
||||
| `-e`, `--env` | `stringArray` | | Set environment variables |
|
||||
| `--index` | `int` | `1` | index of the container if there are multiple instances of a service [default: 1]. |
|
||||
| `-T`, `--no-TTY` | | | Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY. |
|
||||
| `--privileged` | | | Give extended privileges to the process. |
|
||||
| `-u`, `--user` | `string` | | Run the command as this user. |
|
||||
| `-w`, `--workdir` | `string` | | Path to workdir directory for this command. |
|
||||
| Name | Type | Default | Description |
|
||||
|:------------------|:--------------|:--------|:---------------------------------------------------------------------------------|
|
||||
| `-d`, `--detach` | | | Detached mode: Run command in the background. |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `-e`, `--env` | `stringArray` | | Set environment variables |
|
||||
| `--index` | `int` | `0` | index of the container if service has multiple replicas |
|
||||
| `-T`, `--no-TTY` | | | Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY. |
|
||||
| `--privileged` | | | Give extended privileges to the process. |
|
||||
| `-u`, `--user` | `string` | | Run the command as this user. |
|
||||
| `-w`, `--workdir` | `string` | | Path to workdir directory for this command. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,9 +5,11 @@ List images used by the created containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-q`, `--quiet` | | | Only display IDs |
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------|:---------|:--------|:--------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--format` | `string` | `table` | Format the output. Values: [table \| json]. |
|
||||
| `-q`, `--quiet` | | | Only display IDs |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,10 +5,11 @@ Force stop service containers.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `-s`, `--signal` | `string` | `SIGKILL` | SIGNAL to send to the container. |
|
||||
| Name | Type | Default | Description |
|
||||
|:-------------------|:---------|:----------|:----------------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `-s`, `--signal` | `string` | `SIGKILL` | SIGNAL to send to the container. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,15 +5,16 @@ View output from containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-f`, `--follow` | | | Follow log output. |
|
||||
| `--no-color` | | | Produce monochrome output. |
|
||||
| `--no-log-prefix` | | | Don't print prefix in logs. |
|
||||
| `--since` | `string` | | Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) |
|
||||
| `--tail` | `string` | `all` | Number of lines to show from the end of the logs for each container. |
|
||||
| `-t`, `--timestamps` | | | Show timestamps. |
|
||||
| `--until` | `string` | | Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) |
|
||||
| Name | Type | Default | Description |
|
||||
|:---------------------|:---------|:--------|:-----------------------------------------------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `-f`, `--follow` | | | Follow log output. |
|
||||
| `--no-color` | | | Produce monochrome output. |
|
||||
| `--no-log-prefix` | | | Don't print prefix in logs. |
|
||||
| `--since` | `string` | | Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) |
|
||||
| `-n`, `--tail` | `string` | `all` | Number of lines to show from the end of the logs for each container. |
|
||||
| `-t`, `--timestamps` | | | Show timestamps. |
|
||||
| `--until` | `string` | | Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,12 +5,13 @@ List running compose projects
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-a`, `--all` | | | Show all stopped Compose projects |
|
||||
| `--filter` | `filter` | | Filter output based on conditions provided. |
|
||||
| `--format` | `string` | `pretty` | Format the output. Values: [pretty \| json]. |
|
||||
| `-q`, `--quiet` | | | Only display IDs. |
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------|:---------|:--------|:--------------------------------------------|
|
||||
| `-a`, `--all` | | | Show all stopped Compose projects |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--filter` | `filter` | | Filter output based on conditions provided. |
|
||||
| `--format` | `string` | `table` | Format the output. Values: [table \| json]. |
|
||||
| `-q`, `--quiet` | | | Only display IDs. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
<!---MARKER_GEN_START-->
|
||||
Pause services
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:------------|:-----|:--------|:--------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
|
||||
@@ -5,10 +5,11 @@ Print the public port for a port binding.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--index` | `int` | `1` | index of the container if service has multiple replicas |
|
||||
| `--protocol` | `string` | `tcp` | tcp or udp |
|
||||
| Name | Type | Default | Description |
|
||||
|:-------------|:---------|:--------|:--------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--index` | `int` | `0` | index of the container if service has multiple replicas |
|
||||
| `--protocol` | `string` | `tcp` | tcp or udp |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,14 +5,15 @@ List containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-a`, `--all` | | | Show all stopped containers (including those created by the run command) |
|
||||
| [`--filter`](#filter) | `string` | | Filter services by a property (supported filters: status). |
|
||||
| [`--format`](#format) | `string` | `pretty` | Format the output. Values: [pretty \| json] |
|
||||
| `-q`, `--quiet` | | | Only display IDs |
|
||||
| `--services` | | | Display services |
|
||||
| [`--status`](#status) | `stringArray` | | Filter services by status. Values: [paused \| restarting \| removing \| running \| dead \| created \| exited] |
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------------|:--------------|:--------|:--------------------------------------------------------------------------------------------------------------|
|
||||
| `-a`, `--all` | | | Show all stopped containers (including those created by the run command) |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| [`--filter`](#filter) | `string` | | Filter services by a property (supported filters: status). |
|
||||
| [`--format`](#format) | `string` | `table` | Format the output. Values: [table \| json] |
|
||||
| `-q`, `--quiet` | | | Only display IDs |
|
||||
| `--services` | | | Display services |
|
||||
| [`--status`](#status) | `stringArray` | | Filter services by status. Values: [paused \| restarting \| removing \| running \| dead \| created \| exited] |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
@@ -20,13 +21,20 @@ List containers
|
||||
## Description
|
||||
|
||||
Lists containers for a Compose project, with current status and exposed ports.
|
||||
By default, both running and stopped containers are shown:
|
||||
|
||||
```console
|
||||
$ docker compose ps
|
||||
NAME COMMAND SERVICE STATUS PORTS
|
||||
example-bar-1 "/docker-entrypoint.…" bar exited (0)
|
||||
example-foo-1 "/docker-entrypoint.…" foo running 0.0.0.0:8080->80/tcp
|
||||
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
|
||||
example-foo-1 alpine "/entrypoint.…" foo 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp
|
||||
```
|
||||
|
||||
By default, only running containers are shown. `--all` flag can be used to include stopped containers
|
||||
|
||||
```console
|
||||
$ docker compose ps --all
|
||||
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
|
||||
example-foo-1 alpine "/entrypoint.…" foo 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp
|
||||
example-bar-1 alpine "/entrypoint.…" bar 4 seconds ago exited (0)
|
||||
```
|
||||
|
||||
## Examples
|
||||
@@ -89,12 +97,12 @@ to show only containers that are running or only containers that have exited:
|
||||
|
||||
```console
|
||||
$ docker compose ps --status=running
|
||||
NAME COMMAND SERVICE STATUS PORTS
|
||||
example-foo-1 "/docker-entrypoint.…" foo running 0.0.0.0:8080->80/tcp
|
||||
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
|
||||
example-foo-1 alpine "/entrypoint.…" foo 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp
|
||||
|
||||
$ docker compose ps --status=exited
|
||||
NAME COMMAND SERVICE STATUS PORTS
|
||||
example-bar-1 "/docker-entrypoint.…" bar exited (0)
|
||||
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
|
||||
example-bar-1 alpine "/entrypoint.…" bar 4 seconds ago exited (0)
|
||||
```
|
||||
|
||||
### <a name="filter"></a> Filter containers by status (--filter)
|
||||
@@ -105,12 +113,8 @@ this time using the `--filter` flag:
|
||||
|
||||
```console
|
||||
$ docker compose ps --filter status=running
|
||||
NAME COMMAND SERVICE STATUS PORTS
|
||||
example-foo-1 "/docker-entrypoint.…" foo running 0.0.0.0:8080->80/tcp
|
||||
|
||||
$ docker compose ps --filter status=running
|
||||
NAME COMMAND SERVICE STATUS PORTS
|
||||
example-bar-1 "/docker-entrypoint.…" bar exited (0)
|
||||
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
|
||||
example-foo-1 alpine "/entrypoint.…" foo 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp
|
||||
```
|
||||
|
||||
The `docker compose ps` command currently only supports the `--filter status=<status>`
|
||||
|
||||
@@ -5,11 +5,13 @@ Pull service images
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--ignore-pull-failures` | | | Pull what it can and ignores images with pull failures |
|
||||
| `--include-deps` | | | Also pull services declared as dependencies |
|
||||
| `-q`, `--quiet` | | | Pull without printing progress information |
|
||||
| Name | Type | Default | Description |
|
||||
|:-------------------------|:-----|:--------|:--------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--ignore-buildable` | | | Ignore images that can be built. |
|
||||
| `--ignore-pull-failures` | | | Pull what it can and ignores images with pull failures. |
|
||||
| `--include-deps` | | | Also pull services declared as dependencies. |
|
||||
| `-q`, `--quiet` | | | Pull without printing progress information. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
@@ -62,3 +64,6 @@ $ docker compose pull db
|
||||
⠹ 77a0c198cde5 Waiting 9.3s
|
||||
⠹ c8752d5b785c Waiting 9.3s
|
||||
```
|
||||
|
||||
`docker compose pull` will try to pull image for services with a build section. If pull fails, it will let
|
||||
user know this service image MUST be built. You can skip this by setting `--ignore-buildable` flag
|
||||
|
||||
@@ -5,10 +5,12 @@ Push service images
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--ignore-push-failures` | | | Push what it can and ignores images with push failures |
|
||||
| `-q`, `--quiet` | | | Push without printing progress information |
|
||||
| Name | Type | Default | Description |
|
||||
|:-------------------------|:-----|:--------|:-------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--ignore-push-failures` | | | Push what it can and ignores images with push failures |
|
||||
| `--include-deps` | | | Also push images of services declared as dependencies |
|
||||
| `-q`, `--quiet` | | | Push without printing progress information |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,9 +5,11 @@ Restart service containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds |
|
||||
| Name | Type | Default | Description |
|
||||
|:------------------|:------|:--------|:--------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--no-deps` | | | Don't restart dependent services. |
|
||||
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -10,11 +10,12 @@ Any data which is not in a volume will be lost.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-f`, `--force` | | | Don't ask to confirm removal |
|
||||
| `-s`, `--stop` | | | Stop the containers, if required, before removing |
|
||||
| `-v`, `--volumes` | | | Remove any anonymous volumes attached to containers |
|
||||
| Name | Type | Default | Description |
|
||||
|:------------------|:-----|:--------|:----------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `-f`, `--force` | | | Don't ask to confirm removal |
|
||||
| `-s`, `--stop` | | | Stop the containers, if required, before removing |
|
||||
| `-v`, `--volumes` | | | Remove any anonymous volumes attached to containers |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -5,25 +5,29 @@ Run a one-off command on a service.
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--build` | | | Build image before starting container. |
|
||||
| `-d`, `--detach` | | | Run container in background and print container ID |
|
||||
| `--entrypoint` | `string` | | Override the entrypoint of the image |
|
||||
| `-e`, `--env` | `stringArray` | | Set environment variables |
|
||||
| `-i`, `--interactive` | | | Keep STDIN open even if not attached. |
|
||||
| `-l`, `--label` | `stringArray` | | Add or override a label |
|
||||
| `--name` | `string` | | Assign a name to the container |
|
||||
| `-T`, `--no-TTY` | | | Disable pseudo-TTY allocation (default: auto-detected). |
|
||||
| `--no-deps` | | | Don't start linked services. |
|
||||
| `-p`, `--publish` | `stringArray` | | Publish a container's port(s) to the host. |
|
||||
| `--quiet-pull` | | | Pull without printing progress information. |
|
||||
| `--rm` | | | Automatically remove the container when it exits |
|
||||
| `--service-ports` | | | Run command with the service's ports enabled and mapped to the host. |
|
||||
| `--use-aliases` | | | Use the service's network useAliases in the network(s) the container connects to. |
|
||||
| `-u`, `--user` | `string` | | Run as specified username or uid |
|
||||
| `-v`, `--volume` | `stringArray` | | Bind mount a volume. |
|
||||
| `-w`, `--workdir` | `string` | | Working directory inside the container |
|
||||
| Name | Type | Default | Description |
|
||||
|:----------------------|:--------------|:--------|:----------------------------------------------------------------------------------|
|
||||
| `--build` | | | Build image before starting container. |
|
||||
| `--cap-add` | `list` | | Add Linux capabilities |
|
||||
| `--cap-drop` | `list` | | Drop Linux capabilities |
|
||||
| `-d`, `--detach` | | | Run container in background and print container ID |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--entrypoint` | `string` | | Override the entrypoint of the image |
|
||||
| `-e`, `--env` | `stringArray` | | Set environment variables |
|
||||
| `-i`, `--interactive` | | | Keep STDIN open even if not attached. |
|
||||
| `-l`, `--label` | `stringArray` | | Add or override a label |
|
||||
| `--name` | `string` | | Assign a name to the container |
|
||||
| `-T`, `--no-TTY` | | | Disable pseudo-TTY allocation (default: auto-detected). |
|
||||
| `--no-deps` | | | Don't start linked services. |
|
||||
| `-p`, `--publish` | `stringArray` | | Publish a container's port(s) to the host. |
|
||||
| `--quiet-pull` | | | Pull without printing progress information. |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `--rm` | | | Automatically remove the container when it exits |
|
||||
| `--service-ports` | | | Run command with the service's ports enabled and mapped to the host. |
|
||||
| `--use-aliases` | | | Use the service's network useAliases in the network(s) the container connects to. |
|
||||
| `-u`, `--user` | `string` | | Run as specified username or uid |
|
||||
| `-v`, `--volume` | `stringArray` | | Bind mount a volume. |
|
||||
| `-w`, `--workdir` | `string` | | Working directory inside the container |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
@@ -32,7 +36,7 @@ Run a one-off command on a service.
|
||||
|
||||
Runs a one-time command against a service.
|
||||
|
||||
the following command starts the `web` service and runs `bash` as its command:
|
||||
The following command starts the `web` service and runs `bash` as its command:
|
||||
|
||||
```console
|
||||
$ docker compose run web bash
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
<!---MARKER_GEN_START-->
|
||||
Start services
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:------------|:-----|:--------|:--------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
|
||||
@@ -5,9 +5,10 @@ Stop services
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds |
|
||||
| Name | Type | Default | Description |
|
||||
|:------------------|:------|:--------|:--------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
<!---MARKER_GEN_START-->
|
||||
Display the running processes
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:------------|:-----|:--------|:--------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
<!---MARKER_GEN_START-->
|
||||
Unpause services
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:------------|:-----|:--------|:--------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
|
||||
@@ -5,29 +5,33 @@ Create and start containers
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `--abort-on-container-exit` | | | Stops all containers if any container was stopped. Incompatible with -d |
|
||||
| `--always-recreate-deps` | | | Recreate dependent containers. Incompatible with --no-recreate. |
|
||||
| `--attach` | `stringArray` | | Attach to service output. |
|
||||
| `--attach-dependencies` | | | Attach to dependent containers. |
|
||||
| `--build` | | | Build images before starting containers. |
|
||||
| `-d`, `--detach` | | | Detached mode: Run containers in the background |
|
||||
| `--exit-code-from` | `string` | | Return the exit code of the selected service container. Implies --abort-on-container-exit |
|
||||
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed. |
|
||||
| `--no-build` | | | Don't build an image, even if it's missing. |
|
||||
| `--no-color` | | | Produce monochrome output. |
|
||||
| `--no-deps` | | | Don't start linked services. |
|
||||
| `--no-log-prefix` | | | Don't print prefix in logs. |
|
||||
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
|
||||
| `--no-start` | | | Don't start the services after creating them. |
|
||||
| `--pull` | `string` | `missing` | Pull image before running ("always"\|"missing"\|"never") |
|
||||
| `--quiet-pull` | | | Pull without printing progress information. |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `-V`, `--renew-anon-volumes` | | | Recreate anonymous volumes instead of retrieving data from the previous containers. |
|
||||
| `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. |
|
||||
| `-t`, `--timeout` | `int` | `10` | Use this timeout in seconds for container shutdown when attached or when containers are already running. |
|
||||
| `--wait` | | | Wait for services to be running\|healthy. Implies detached mode. |
|
||||
| Name | Type | Default | Description |
|
||||
|:-----------------------------|:--------------|:----------|:---------------------------------------------------------------------------------------------------------|
|
||||
| `--abort-on-container-exit` | | | Stops all containers if any container was stopped. Incompatible with -d |
|
||||
| `--always-recreate-deps` | | | Recreate dependent containers. Incompatible with --no-recreate. |
|
||||
| `--attach` | `stringArray` | | Attach to service output. |
|
||||
| `--attach-dependencies` | | | Attach to dependent containers. |
|
||||
| `--build` | | | Build images before starting containers. |
|
||||
| `-d`, `--detach` | | | Detached mode: Run containers in the background |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `--exit-code-from` | `string` | | Return the exit code of the selected service container. Implies --abort-on-container-exit |
|
||||
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed. |
|
||||
| `--no-attach` | `stringArray` | | Don't attach to specified service. |
|
||||
| `--no-build` | | | Don't build an image, even if it's missing. |
|
||||
| `--no-color` | | | Produce monochrome output. |
|
||||
| `--no-deps` | | | Don't start linked services. |
|
||||
| `--no-log-prefix` | | | Don't print prefix in logs. |
|
||||
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
|
||||
| `--no-start` | | | Don't start the services after creating them. |
|
||||
| `--pull` | `string` | `missing` | Pull image before running ("always"\|"missing"\|"never") |
|
||||
| `--quiet-pull` | | | Pull without printing progress information. |
|
||||
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
|
||||
| `-V`, `--renew-anon-volumes` | | | Recreate anonymous volumes instead of retrieving data from the previous containers. |
|
||||
| `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. |
|
||||
| `-t`, `--timeout` | `int` | `0` | Use this timeout in seconds for container shutdown when attached or when containers are already running. |
|
||||
| `--timestamps` | | | Show timestamps. |
|
||||
| `--wait` | | | Wait for services to be running\|healthy. Implies detached mode. |
|
||||
| `--wait-timeout` | `int` | `0` | timeout waiting for application to be running\|healthy. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
@@ -39,6 +43,9 @@ Builds, (re)creates, starts, and attaches to containers for a service.
|
||||
Unless they are already running, this command also starts any linked services.
|
||||
|
||||
The `docker compose up` command aggregates the output of each container (like `docker compose logs --follow` does).
|
||||
One can optionally select a subset of services to attach to using `--attach` flag, or exclude some services using
|
||||
`--no-attach` to prevent output to be flooded by some verbose services.
|
||||
|
||||
When the command exits, all containers are stopped. Running `docker compose up --detach` starts the containers in the
|
||||
background and leaves them running.
|
||||
|
||||
|
||||
@@ -5,10 +5,11 @@ Show the Docker Compose version information
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `-f`, `--format` | `string` | | Format the output. Values: [pretty \| json]. (Default: pretty) |
|
||||
| `--short` | | | Shows only Compose's version number. |
|
||||
| Name | Type | Default | Description |
|
||||
|:-----------------|:---------|:--------|:---------------------------------------------------------------|
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
| `-f`, `--format` | `string` | | Format the output. Values: [pretty \| json]. (Default: pretty) |
|
||||
| `--short` | | | Shows only Compose's version number. |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
15
docs/reference/compose_wait.md
Normal file
15
docs/reference/compose_wait.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# docker compose wait
|
||||
|
||||
<!---MARKER_GEN_START-->
|
||||
Block until the first service container stops
|
||||
|
||||
### Options
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|:-----------------|:-----|:--------|:---------------------------------------------|
|
||||
| `--down-project` | | | Drops project when the first container stops |
|
||||
| `--dry-run` | | | Execute command in dry run mode |
|
||||
|
||||
|
||||
<!---MARKER_GEN_END-->
|
||||
|
||||
@@ -63,12 +63,19 @@ long: |-
|
||||
|
||||
### Use `-p` to specify a project name
|
||||
|
||||
Each configuration has a project name. If you supply a `-p` flag, you can specify a project name. If you don’t
|
||||
specify the flag, Compose uses the current directory name.
|
||||
Project name can also be set by `COMPOSE_PROJECT_NAME` environment variable.
|
||||
|
||||
Many Compose subcommands can be run without a Compose file by passing
|
||||
the project name.
|
||||
Each configuration has a project name. Compose sets the project name using
|
||||
the following mechanisms, in order of precedence:
|
||||
- The `-p` command line flag
|
||||
- The `COMPOSE_PROJECT_NAME` environment variable
|
||||
- The top level `name:` variable from the config file (or the last `name:`
|
||||
from a series of config files specified using `-f`)
|
||||
- The `basename` of the project directory containing the config file (or
|
||||
containing the first config file specified using `-f`)
|
||||
- The `basename` of the current directory if no config file is specified
|
||||
Project names must contain only lowercase letters, decimal digits, dashes,
|
||||
and underscores, and must begin with a lowercase letter or decimal digit. If
|
||||
the `basename` of the project directory or current directory violates this
|
||||
constraint, you must use one of the other mechanisms.
|
||||
|
||||
```console
|
||||
$ docker compose -p my_project ps -a
|
||||
@@ -89,24 +96,58 @@ long: |-
|
||||
|
||||
Profiles can also be set by `COMPOSE_PROFILES` environment variable.
|
||||
|
||||
### Configuring parallelism
|
||||
|
||||
Use `--parallel` to specify the maximum level of parallelism for concurrent engine calls.
|
||||
Calling `docker compose --parallel 1 pull` will pull the pullable images defined in the Compose file
|
||||
one at a time. This can also be used to control build concurrency.
|
||||
|
||||
Parallelism can also be set by the `COMPOSE_PARALLEL_LIMIT` environment variable.
|
||||
|
||||
### Set up environment variables
|
||||
|
||||
You can set environment variables for various docker compose options, including the `-f`, `-p` and `--profiles` flags.
|
||||
|
||||
Setting the `COMPOSE_FILE` environment variable is equivalent to passing the `-f` flag,
|
||||
`COMPOSE_PROJECT_NAME` environment variable does the same as the `-p` flag,
|
||||
and `COMPOSE_PROFILES` environment variable is equivalent to the `--profiles` flag.
|
||||
`COMPOSE_PROFILES` environment variable is equivalent to the `--profiles` flag
|
||||
and `COMPOSE_PARALLEL_LIMIT` does the same as the `--parallel` flag.
|
||||
|
||||
If flags are explicitly set on the command line, the associated environment variable is ignored.
|
||||
|
||||
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
|
||||
containers for the project.
|
||||
|
||||
### Use Dry Run mode to test your command
|
||||
|
||||
Use `--dry-run` flag to test a command without changing your application stack state.
|
||||
Dry Run mode shows you all the steps Compose applies when executing a command, for example:
|
||||
```console
|
||||
$ docker compose --dry-run up --build -d
|
||||
[+] Pulling 1/1
|
||||
✔ DRY-RUN MODE - db Pulled 0.9s
|
||||
[+] Running 10/8
|
||||
✔ DRY-RUN MODE - build service backend 0.0s
|
||||
✔ DRY-RUN MODE - ==> ==> writing image dryRun-754a08ddf8bcb1cf22f310f09206dd783d42f7dd 0.0s
|
||||
✔ DRY-RUN MODE - ==> ==> naming to nginx-golang-mysql-backend 0.0s
|
||||
✔ DRY-RUN MODE - Network nginx-golang-mysql_default Created 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-db-1 Created 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-backend-1 Created 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-proxy-1 Created 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-db-1 Healthy 0.5s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-backend-1 Started 0.0s
|
||||
✔ DRY-RUN MODE - Container nginx-golang-mysql-proxy-1 Started Started
|
||||
```
|
||||
From the example above, you can see that the first step is to pull the image defined by `db` service, then build the `backend` service.
|
||||
Next, the containers are created. The `db` service is started, and the `backend` and `proxy` wait until the `db` service is healthy before starting.
|
||||
|
||||
Dry Run mode works with almost all commands. You cannot use Dry Run mode with a command that doesn't change the state of a Compose stack such as `ps`, `ls`, `logs` for example.
|
||||
usage: docker compose
|
||||
pname: docker
|
||||
plink: docker.yaml
|
||||
cname:
|
||||
- docker compose build
|
||||
- docker compose convert
|
||||
- docker compose config
|
||||
- docker compose cp
|
||||
- docker compose create
|
||||
- docker compose down
|
||||
@@ -130,9 +171,10 @@ cname:
|
||||
- docker compose unpause
|
||||
- docker compose up
|
||||
- docker compose version
|
||||
- docker compose wait
|
||||
clink:
|
||||
- docker_compose_build.yaml
|
||||
- docker_compose_convert.yaml
|
||||
- docker_compose_config.yaml
|
||||
- docker_compose_cp.yaml
|
||||
- docker_compose_create.yaml
|
||||
- docker_compose_down.yaml
|
||||
@@ -156,6 +198,7 @@ clink:
|
||||
- docker_compose_unpause.yaml
|
||||
- docker_compose_up.yaml
|
||||
- docker_compose_version.yaml
|
||||
- docker_compose_wait.yaml
|
||||
options:
|
||||
- option: ansi
|
||||
value_type: string
|
||||
@@ -178,8 +221,19 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: env-file
|
||||
value_type: string
|
||||
value_type: stringArray
|
||||
default_value: '[]'
|
||||
description: Specify an alternate environment file.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
@@ -208,6 +262,16 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: parallel
|
||||
value_type: int
|
||||
default_value: "-1"
|
||||
description: Control max parallelism, -1 for unlimited
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: profile
|
||||
value_type: stringArray
|
||||
default_value: '[]'
|
||||
@@ -218,6 +282,16 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: progress
|
||||
value_type: string
|
||||
default_value: auto
|
||||
description: Set type of progress output (auto, tty, plain, quiet)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: project-directory
|
||||
value_type: string
|
||||
description: |-
|
||||
@@ -273,6 +347,7 @@ options:
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
31
docs/reference/docker_compose_alpha.yaml
Normal file
31
docs/reference/docker_compose_alpha.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
command: docker compose alpha
|
||||
short: Experimental commands
|
||||
long: Experimental commands
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
cname:
|
||||
- docker compose alpha publish
|
||||
- docker compose alpha viz
|
||||
- docker compose alpha watch
|
||||
clink:
|
||||
- docker_compose_alpha_publish.yaml
|
||||
- docker_compose_alpha_viz.yaml
|
||||
- docker_compose_alpha_watch.yaml
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: true
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
|
||||
14
docs/reference/docker_compose_alpha_dry-run.yaml
Normal file
14
docs/reference/docker_compose_alpha_dry-run.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
command: docker compose alpha dry-run
|
||||
short: |
|
||||
EXPERIMENTAL - Dry run command allow you to test a command without applying changes
|
||||
long: |
|
||||
EXPERIMENTAL - Dry run command allow you to test a command without applying changes
|
||||
usage: docker compose alpha dry-run -- [COMMAND...]
|
||||
pname: docker compose alpha
|
||||
plink: docker_compose_alpha.yaml
|
||||
deprecated: false
|
||||
experimental: false
|
||||
experimentalcli: true
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
|
||||
24
docs/reference/docker_compose_alpha_publish.yaml
Normal file
24
docs/reference/docker_compose_alpha_publish.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
command: docker compose alpha publish
|
||||
short: Publish compose application
|
||||
long: Publish compose application
|
||||
usage: docker compose alpha publish [OPTIONS] [REPOSITORY]
|
||||
pname: docker compose alpha
|
||||
plink: docker_compose_alpha.yaml
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: true
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
|
||||
77
docs/reference/docker_compose_alpha_viz.yaml
Normal file
77
docs/reference/docker_compose_alpha_viz.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
command: docker compose alpha viz
|
||||
short: EXPERIMENTAL - Generate a graphviz graph from your compose file
|
||||
long: EXPERIMENTAL - Generate a graphviz graph from your compose file
|
||||
usage: docker compose alpha viz [OPTIONS]
|
||||
pname: docker compose alpha
|
||||
plink: docker_compose_alpha.yaml
|
||||
options:
|
||||
- option: image
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Include service's image name in output graph
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: indentation-size
|
||||
value_type: int
|
||||
default_value: "1"
|
||||
description: Number of tabs or spaces to use for indentation
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: networks
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Include service's attached networks in output graph
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: ports
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Include service's exposed ports in output graph
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: spaces
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: |-
|
||||
If given, space character ' ' will be used to indent,
|
||||
otherwise tab character '\t' will be used
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: true
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
|
||||
37
docs/reference/docker_compose_alpha_watch.yaml
Normal file
37
docs/reference/docker_compose_alpha_watch.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
command: docker compose alpha watch
|
||||
short: |
|
||||
EXPERIMENTAL - Watch build context for service and rebuild/refresh containers when files are updated
|
||||
long: |
|
||||
EXPERIMENTAL - Watch build context for service and rebuild/refresh containers when files are updated
|
||||
usage: docker compose alpha watch [SERVICE...]
|
||||
pname: docker compose alpha
|
||||
plink: docker_compose_alpha.yaml
|
||||
options:
|
||||
- option: quiet
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: hide build output
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: true
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
|
||||
@@ -24,6 +24,15 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: builder
|
||||
value_type: string
|
||||
description: Set builder to use.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: compress
|
||||
value_type: bool
|
||||
default_value: "true"
|
||||
@@ -46,11 +55,12 @@ options:
|
||||
swarm: false
|
||||
- option: memory
|
||||
shorthand: m
|
||||
value_type: string
|
||||
value_type: bytes
|
||||
default_value: "0"
|
||||
description: |
|
||||
Set memory limit for the build container. Not supported on buildkit yet.
|
||||
Set memory limit for the build container. Not supported by BuildKit.
|
||||
deprecated: false
|
||||
hidden: true
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -89,9 +99,9 @@ options:
|
||||
- option: progress
|
||||
value_type: string
|
||||
default_value: auto
|
||||
description: Set type of progress output (auto, tty, plain, quiet)
|
||||
description: Set type of ui output (auto, tty, plain, quiet)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
hidden: true
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
@@ -106,6 +116,16 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: push
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Push service images.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: quiet
|
||||
shorthand: q
|
||||
value_type: bool
|
||||
@@ -127,7 +147,19 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
160
docs/reference/docker_compose_config.yaml
Normal file
160
docs/reference/docker_compose_config.yaml
Normal file
@@ -0,0 +1,160 @@
|
||||
command: docker compose config
|
||||
aliases: docker compose config, docker compose convert
|
||||
short: Parse, resolve and render compose file in canonical format
|
||||
long: |-
|
||||
`docker compose config` renders the actual data model to be applied on the Docker engine.
|
||||
it merges the Compose files set by `-f` flags, resolves variables in the Compose file, and expands short-notation into
|
||||
the canonical format.
|
||||
usage: docker compose config [OPTIONS] [SERVICE...]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
- option: format
|
||||
value_type: string
|
||||
default_value: yaml
|
||||
description: 'Format the output. Values: [yaml | json]'
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: hash
|
||||
value_type: string
|
||||
description: Print the service config hash, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: images
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Print the image names, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: no-consistency
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: |
|
||||
Don't check model consistency - warning: may produce invalid Compose output
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: no-interpolate
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Don't interpolate environment variables.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: no-normalize
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Don't normalize compose model.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: no-path-resolution
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Don't resolve file paths.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: output
|
||||
shorthand: o
|
||||
value_type: string
|
||||
description: Save to file (default to stdout)
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: profiles
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Print the profile names, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: quiet
|
||||
shorthand: q
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Only validate the configuration, don't print anything.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: resolve-image-digests
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Pin image tags to digests.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: services
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Print the service names, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: volumes
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Print the volume names, one per line.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
|
||||
@@ -10,7 +10,7 @@ options:
|
||||
- option: all
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Copy to all the containers of the service.
|
||||
description: copy to all the containers of the service.
|
||||
deprecated: true
|
||||
hidden: true
|
||||
experimental: false
|
||||
@@ -42,8 +42,18 @@ options:
|
||||
- option: index
|
||||
value_type: int
|
||||
default_value: "0"
|
||||
description: |
|
||||
Index of the container if there are multiple instances of a service .
|
||||
description: index of the container if service has multiple replicas
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
@@ -51,6 +61,7 @@ options:
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -57,7 +57,40 @@ options:
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: remove-orphans
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Remove containers for services not defined in the Compose file.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
- option: scale
|
||||
value_type: stringArray
|
||||
default_value: '[]'
|
||||
description: |
|
||||
Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
@@ -14,7 +14,7 @@ long: |-
|
||||
Anonymous volumes are not removed by default. However, as they don’t have a stable name, they will not be automatically
|
||||
mounted by a subsequent `up`. For data that needs to persist between updates, use explicit paths as bind mounts or
|
||||
named volumes.
|
||||
usage: docker compose down [OPTIONS]
|
||||
usage: docker compose down [OPTIONS] [SERVICES]
|
||||
pname: docker compose
|
||||
plink: docker_compose.yaml
|
||||
options:
|
||||
@@ -41,7 +41,7 @@ options:
|
||||
- option: timeout
|
||||
shorthand: t
|
||||
value_type: int
|
||||
default_value: "10"
|
||||
default_value: "0"
|
||||
description: Specify a shutdown timeout in seconds
|
||||
deprecated: false
|
||||
hidden: false
|
||||
@@ -54,7 +54,18 @@ options:
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: |
|
||||
Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.
|
||||
Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers.
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
inherited_options:
|
||||
- option: dry-run
|
||||
value_type: bool
|
||||
default_value: "false"
|
||||
description: Execute command in dry run mode
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
@@ -62,6 +73,7 @@ options:
|
||||
kubernetes: false
|
||||
swarm: false
|
||||
deprecated: false
|
||||
hidden: false
|
||||
experimental: false
|
||||
experimentalcli: false
|
||||
kubernetes: false
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user