Compare commits

...

204 Commits

Author SHA1 Message Date
Milas Bowman
3371227794 chore(desktop): revised feature detection for file shares
Unfortunately, the feature flag mechanism for experimental features
isn't adequate. To avoid some edge cases where Compose might try to
use Synchronized file shares with Desktop when the feature isn't
available, we need to query a new endpoint.

Before we move any of this out of experimental, we need to improve
the integration here with Desktop & Compose so that we get all the
necessary feature/experiment state up-front to reduce the quantity
of IPC calls needed up-front.

For now, there's some intentional redundancy to avoid making this
extra call if we can avoid it. The actual endpoint is very cheap/
fast, but every IPC call is a potential point of of failure, so
it's worth it.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-03-22 18:16:27 +01:00
Joana Hrotko
e9dc82011f Add Navigation Menu to compose up
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-03-22 17:48:25 +01:00
Nicolas De Loof
3950460703 Add support for volume Subpath option
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-22 14:33:56 +01:00
Nicolas De Loof
3b541b071c Bump docker v26.0.0
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-22 14:33:56 +01:00
Nicolas De Loof
25671ae622 introduce config --variables to list compose model variables
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-22 13:51:30 +01:00
Sebastian Correa
0191e69d5b Fix docs on default build image name
150fd4b8cf changed the default separator from _ to -, but the docker compose build docs still mention _.

Signed-off-by: Sebastian Correa <43179146+sebastian-correa@users.noreply.github.com>
2024-03-22 13:42:13 +01:00
Nicolas De Loof
897d239fcb Bump compose-go to v2.0.2
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-22 11:21:14 +01:00
Nicolas De Loof
c5a760ce43 add support for annotations
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-22 10:45:44 +01:00
Joana H
759d3bc9f9 Merge pull request #11647 from milas/revert-compose-go-201
chore(deps): revert "Bump compose-go to v2.0.1"
2024-03-21 18:00:34 +00:00
Milas Bowman
26f687a12b Revert "Bump compose-go to v2.0.1"
This reverts commit ad41461309.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-03-21 13:43:44 -04:00
Nicolas De Loof
ad41461309 Bump compose-go to v2.0.1
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-21 15:54:41 +01:00
Milas Bowman
db4ed89528 feat(desktop): synchronized file share integration (#11614) 2024-03-20 14:41:24 -04:00
Milas Bowman
1b5fa3b93f feat(experiments): add experimental feature state (#11633)
Use environment variable for global opt-out and Docker Desktop (if
available) to determine specific experiment states.

In the future, we'll allow per-feature opt-in/opt-out via env vars
as well, but currently there is a single `COMPOSE_EXPERIMENTAL` env
var that can be used to opt-out of all experimental features
independently of Docker Desktop configuration.
2024-03-20 13:44:27 +00:00
Guillaume Lours
86cd52370a Merge pull request #11630 from ndeloof/config_json
fix `compose config --format json`
2024-03-18 16:11:18 +01:00
Guillaume Lours
4f97edf355 reduce timeout of the Otel tracing command
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-03-18 08:40:36 +01:00
Nicolas De Loof
bc5fc6ba7e fix compose config --format json
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-18 08:09:54 +01:00
Nicolas De Loof
f937e42aaf Bump compose-go v2.0.0
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-15 13:02:46 +01:00
Andrew Onyshchuk
f46ca459d2 services shell completion bugfix
Signed-off-by: Andrew Onyshchuk <andryk.rv@gmail.com>
2024-03-15 10:47:30 +01:00
Nicolas De Loof
b2d4c1b865 fix TestBuildPlatformsWithCorrectBuildxConfig
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-15 10:38:03 +01:00
Nicolas De Loof
5a1ba0efcf only use ToModel when --no-interpolate is set
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-13 06:48:24 +01:00
Milas Bowman
17d4229e57 feat(desktop): add Docker Desktop detection and client skeleton (#11593) 2024-03-12 09:47:41 -04:00
Milas Bowman
4efb89709c chore(deps): upgrade go to 1.21.8 (#11578) 2024-03-05 22:23:52 +01:00
Milas Bowman
f35449a603 ci(deps): bump moby/moby & docker/cli to v25.0.4 (#11566) 2024-03-05 20:39:18 +00:00
Joana Hrotko
34b11c4f4f Add test summary for test jobs in ci
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-03-01 13:32:04 +01:00
Guillaume Lours
a7acf5fa67 Merge pull request #11535 from ndeloof/simpler
make code simpler
2024-03-01 10:02:12 +01:00
Nicolas De Loof
c525373acb make code simpler
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-03-01 09:55:03 +01:00
Nicolas De Loof
e99b8acea7 avoid duplicated "xx exited with code 0" message
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-29 13:57:17 +01:00
Nicolas De Loof
8ab8df86e0 introduce --watch
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-28 19:04:58 +01:00
Nicolas De Loof
de178267df move code into small functions for better readability
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-28 18:54:43 +01:00
Nicolas De Loof
1680f9a874 restore support for config --no-interpolate
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-28 18:54:43 +01:00
Joana Hrotko
5c4f33702e remove docker cli step in ci.yml
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-02-27 12:50:44 +01:00
Joana H
e2762b144e Merge pull request #11542 from ndeloof/log_attach
get log to manage `attach`
2024-02-27 11:04:46 +00:00
Nicolas De Loof
58ec0e9fb6 get log to manage attach
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-22 18:27:05 +01:00
Guillaume Lours
a7224411b4 Merge pull request #11513 from glours/use-go-ps-pid-lock
Double check watch pid if detected as still running on Windows
2024-02-22 16:21:47 +01:00
Guillaume Lours
c5a88deeba Merge pull request #11536 from glours/bump-compose-go-2.0.0-rc.8
bump compose-go to version v2.0.0-rc.8
2024-02-21 19:57:19 +01:00
Guillaume Lours
349d9f34d0 bump compose-go to version v2.0.0-rc.8
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-02-21 19:41:04 +01:00
Guillaume Lours
9d38ee1726 Merge pull request #11537 from glours/fix-flakyness-run-quiet-pull
use a dedicated compose file for --quiet-pull e2e test
2024-02-21 19:40:01 +01:00
Guillaume Lours
697a48af32 use an dedicated compose file --quiet-pull e2e test
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-02-21 18:59:09 +01:00
Guillaume Lours
9b0d1ffcf8 Add a fallback check of Watch pid on Windows
False positives were detected when checking the previous watch process state

Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-02-19 15:01:38 +01:00
Guillaume Lours
d10a179f3e add support of QuietOption to create command
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-02-19 14:19:01 +01:00
Guillaume Lours
94246f3cac pass QuietOption when starting dependencies from run command
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-02-19 14:19:01 +01:00
Nicolas De Loof
9630cc5808 when ran with ANSI disabled, force progress=plain
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-18 12:33:20 +01:00
Gautham Hullikunte
6c175548b8 Issue-11374: Modified compose up command to respect COMPOSE_REMOVE_ORPHANS environment variable
Signed-off-by: Gautham Hullikunte <46633282+batcity@users.noreply.github.com>
Signed-off-by: Gautham Hullikunte <gautham@Gauthams-MacBook-Pro.local>
2024-02-17 09:37:00 +01:00
Guillaume Lours
f1431b2a48 Merge pull request #11512 from laurazard/bump-engine-ci
ci: bump engine version to `25.0.3`
2024-02-16 15:03:09 +01:00
Laura Brehm
9b0e3d53eb ci: bump engine version to 25.0.3
changes: https://github.com/moby/moby/releases/tag/v25.0.3

(Hopefully, this fixes some networking flakyness)

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-02-16 12:47:24 +00:00
Nicolas De Loof
de3da829ea sort containers to optimize scale down
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-15 17:47:42 +01:00
Nicolas De Loof
c79aabde32 discard stdout for laaarge log test
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-15 16:18:58 +01:00
Guillaume Lours
eb5f7d76fe Merge pull request #11503 from ndeloof/includes_metric
use listeners to collect include metrics
2024-02-15 11:27:19 +01:00
Nicolas De Loof
0aad322140 use listeners to collect include metrics
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-15 11:20:09 +01:00
David Karlsson
b1c06770d4 docs: update cli reference link
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-02-15 08:20:11 +01:00
Guillaume Lours
a220043ca0 Merge pull request #11497 from milas/rm-docker-cp-syncer
chore(watch): remove old `docker cp` implementation
2024-02-14 21:26:05 +01:00
Piotr Dąbrowski
e330f5905b docs: unify no trailing dots in docstrings and help (#11301) 2024-02-14 14:02:37 -05:00
Guillaume Lours
aa56ab3e71 Merge pull request #11492 from jhrotko/use-listeners-for-file-metadata
Use listener for file metadata
2024-02-14 18:04:06 +01:00
jhrotko
16c8099cf8 Use listener for file metadata
Signed-off-by: jhrotko <joana.hrotko@docker.com>
2024-02-14 16:51:56 +00:00
Nicolas De Loof
07bda5960e fix deadlock collecting large logs
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-13 20:15:19 +01:00
Milas Bowman
d203402998 chore(watch): remove old docker cp implementation
This has not been the default for quite a while and required
setting an environment variable to revert back.

The tar implementation is more performant and addresses several
edge cases with the original `docker cp` version, so it's time
to fully retire it.

The scaffolding for multiple sync implementations remains to
support future experimentation here.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-02-13 12:56:53 -05:00
Nicolas De loof
894ab41c3b ci(deps): bump docker/cli to v25.0.3 (#11481)
https://github.com/docker/cli/releases/tag/v25.0.3
https://github.com/moby/moby/releases/tag/v25.0.3
2024-02-12 11:20:31 -05:00
1arp
3ba66453d2 pass All option to backend api.Service when length statuses is not equal to zero
Signed-off-by: 1arp <dekhijaegi@gmail.com>
2024-02-09 16:37:29 +01:00
Guillaume Lours
4ce63f53f7 Merge pull request #11485 from jhrotko/add-otel-build-depends-capabilities
add OTEL build,depends and capabilities to attributes
2024-02-09 12:25:07 +01:00
jhrotko
2eca9313c2 Add OTEL specs: build, depends_on, capabilities (gpu/tpu)
Signed-off-by: jhrotko <joana.hrotko@docker.com>
2024-02-09 10:55:07 +00:00
dependabot[bot]
1fea7c1beb build(deps): bump github.com/opencontainers/image-spec
Bumps [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) from 1.1.0-rc5 to 1.1.0-rc6.
- [Release notes](https://github.com/opencontainers/image-spec/releases)
- [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md)
- [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0-rc5...v1.1.0-rc6)

---
updated-dependencies:
- dependency-name: github.com/opencontainers/image-spec
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-08 15:47:39 +01:00
Milas Bowman
acf2ffb0c7 feat(tracing): add project hash attr
Hash the project config and add it as an attribute. This can be
used to group multiple spans.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-02-08 15:47:25 +01:00
Milas Bowman
0d48a93f57 chore(load): ensure context passed to load
This wasn't always getting passed, so adding it to the wrapper
function where it'll pass the `WithContext()` loader method at
the last moment.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-02-08 15:46:37 +01:00
Laura Brehm
aaa7ef6de5 Include all networks in ContainerCreate call if API >= 1.44
Previously, we included the container's primary network in the
ContainerCreate API call, and then connected the created container
to each extra network one-by-one, by calling NetworkConnect.

However, starting API version 1.44, the ContainerCreate endpoint now
takes multiple EndpointsConfigs, allowing us to just include all the
network configurations there and skip connecting the container to each
extra network separately.

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-02-07 16:21:15 +01:00
Nicolas De Loof
6ef55a531f bump compose-go to v2.0.0-rc.4
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-07 10:44:44 +01:00
Nicolas De Loof
a553db33c6 CI: docker engine version matrix
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-02-05 12:09:45 +01:00
Guillaume Lours
338ffe07a0 Merge pull request #11443 from docker/dependabot/go_modules/github.com/docker/cli-25.0.2incompatible
build(deps): bump github.com/docker/cli from 25.0.1+incompatible to 25.0.2+incompatible
2024-02-01 12:03:18 +01:00
dependabot[bot]
05bec55d21 build(deps): bump github.com/docker/cli
Bumps [github.com/docker/cli](https://github.com/docker/cli) from 25.0.1+incompatible to 25.0.2+incompatible.
- [Commits](https://github.com/docker/cli/compare/v25.0.1...v25.0.2)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 09:44:43 +00:00
Guillaume Lours
3c25af4fe9 Merge pull request #11405 from ndeloof/issue_11392
Fix load .env from project directory when project file is set by COMPOSE_FILE
2024-01-31 10:52:28 +01:00
Milas Bowman
8fdd45cd4c chore(e2e): fix flaky test & standalone behavior (#11382) 2024-01-30 10:49:53 -05:00
CrazyMax
a0954dc59d ci(deps): replace buildkit to fix fsutil issues on Windows (#11426) 2024-01-30 10:48:48 -05:00
jhrotko
0582001810 Fix canonical container name
Signed-off-by: jhrotko <joana.hrotko@docker.com>
2024-01-30 15:12:22 +01:00
Guillaume Lours
ac8ea082a1 Merge pull request #11409 from ndeloof/swarm_overlay_network
don't check external network existence when swarm is enabled
2024-01-29 20:11:13 +01:00
Nicolas De Loof
da1a34a8f2 don't check external network existence when swarm is enabled
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-01-29 20:00:29 +01:00
Guillaume Lours
cdb6eb55d5 Merge pull request #11406 from docker/dependabot/go_modules/github.com/docker/cli-25.0.1incompatible
build(deps): bump github.com/docker/cli from 25.0.0+incompatible to 25.0.1+incompatible
2024-01-29 19:56:56 +01:00
dependabot[bot]
8b023ae07d build(deps): bump github.com/docker/cli
Bumps [github.com/docker/cli](https://github.com/docker/cli) from 25.0.0+incompatible to 25.0.1+incompatible.
- [Commits](https://github.com/docker/cli/compare/v25.0.0...v25.0.1)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-29 19:46:03 +01:00
Guillaume Lours
e08140babe Merge pull request #11407 from docker/dependabot/go_modules/github.com/docker/docker-25.0.1incompatible
build(deps): bump github.com/docker/docker from 25.0.0+incompatible to 25.0.1+incompatible
2024-01-29 19:44:44 +01:00
dependabot[bot]
8c80297c76 build(deps): bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 25.0.0+incompatible to 25.0.1+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v25.0.0...v25.0.1)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-29 19:33:58 +01:00
Guillaume Lours
05f1472f6a Merge pull request #11422 from ndeloof/storage_opts
Add support for storage_opt
2024-01-29 19:33:22 +01:00
Guillaume Lours
5728c43db8 Merge pull request #11410 from thaJeztah/bump_engine_25.0.1
ci(deps): update DOCKER_CLI_VERSION to v25.0.1
2024-01-29 19:31:45 +01:00
Nicolas De Loof
7e991515bc Add support for storage_opt
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-01-29 19:24:23 +01:00
Sebastiaan van Stijn
d979115692 ci(deps): update DOCKER_CLI_VERSION to v25.0.1
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-29 19:23:26 +01:00
Guillaume Lours
c653ddf439 Merge pull request #11411 from laurazard/update-maintainers
Update MAINTAINERS file
2024-01-29 19:22:49 +01:00
Guillaume Lours
a9cbb0f481 Merge pull request #11416 from glours/fix-merge-compose-go-issue
bump compose-go to fix multiple compose files merge issues
2024-01-29 15:41:24 +01:00
Guillaume Lours
71bebc16ee bump compose-go to v2.0.0-rc.3 which fixes multiple compose files merge issues
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-01-29 15:26:26 +01:00
Guillaume Lours
b0dc374abc Merge pull request #11415 from dvdksn/bump-artifact-upload-v4
build(deps): bump actions/upload-artifact from v3 to v4
2024-01-26 09:49:48 +01:00
David Karlsson
25d16d1fb4 build(deps): bump actions/upload-artifact from v3 to v4
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-01-26 09:39:24 +01:00
Laura Brehm
ab97dcc7c5 update MAINTAINERS file
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-01-25 14:28:44 +00:00
Nicolas De Loof
a8bd3b7af1 Fix load .env from project directory when project file is set by COMPOSE_FILE
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-01-25 09:26:22 +01:00
Guillaume Lours
bef8785fc2 Merge pull request #11400 from glours/fix-fsutils-windows
use a custom version of fsutils that fixes a bug on Windows causing all Compose builds to fail
2024-01-24 18:39:58 +01:00
Guillaume Lours
811364b4f8 use a custom version of fsutils that fixes a bug on Windows causing all Compose builds to fail
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-01-24 17:59:13 +01:00
Nicolas De Loof
1551fcb4e6 introduce stopAndRemoveContainer to share logic scaling down
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-01-23 14:16:13 +01:00
Guillaume Lours
143ac0f1b6 Merge pull request #11390 from ndeloof/compose-go-v2.0.0-rc.2
bump compose-go to v2.0.0-rc.2
2024-01-22 17:07:26 +01:00
Nicolas De Loof
eb4249ece4 bump compose-go to v2.0.0-rc.2
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-01-22 12:27:38 +01:00
Milas Bowman
1e8241f67c ci(deps): upgrade to Moby v25.0.0 GA (#11381)
https://github.com/moby/moby/releases/tag/v25.0.0
2024-01-19 12:33:21 -05:00
Sebastiaan van Stijn
388169011f Merge pull request #11359 from dvdksn/docs-update-cli-reference-link
docs: update link to use canonical URL for command
2024-01-19 12:52:12 +01:00
David Karlsson
053a560466 docs: update link to use canonical URL for command
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2024-01-19 11:38:14 +01:00
Laura Brehm
35e262e778 Merge pull request #11372 from thaJeztah/bump_engine_deps 2024-01-18 17:43:24 +00:00
Sebastiaan van Stijn
34ba0bc9dd go.mod: github.com/moby/sys/mountinfo v0.7.1
full diff: https://github.com/moby/sys/compare/mountinfo/v0.6.2...mountinfo/v0.7.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-18 17:59:21 +01:00
Sebastiaan van Stijn
56e38260ea go.mod: github.com/google/uuid v1.5.0
full diff: https://github.com/google/uuid/compare/v1.3.1...v1.5.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-18 17:58:39 +01:00
Guillaume Lours
83e020734d Merge pull request #11368 from glours/bump-compose-go-v2.0.0-rc.1
bump version of compose-go to v2.0.0-rc.1
2024-01-18 10:47:24 +01:00
Guillaume Lours
c28bf5227a bump version of compose-go to v2.0.0-rc.1
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-01-18 10:34:22 +01:00
Guillaume Lours
326ee2ad69 Merge pull request #11367 from docker/dependabot/go_modules/github.com/docker/docker-25.0.0-rc.3incompatible
build(deps): bump github.com/docker/docker from 25.0.0-rc.2+incompatible to 25.0.0-rc.3+incompatible
2024-01-18 10:33:58 +01:00
dependabot[bot]
51c113b623 build(deps): bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 25.0.0-rc.2+incompatible to 25.0.0-rc.3+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v25.0.0-rc.2...v25.0.0-rc.3)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 10:23:59 +01:00
Guillaume Lours
194b8af242 Merge pull request #11365 from docker/dependabot/go_modules/github.com/docker/cli-25.0.0-rc.3incompatible
build(deps): bump github.com/docker/cli from 25.0.0-rc.2+incompatible to 25.0.0-rc.3+incompatible
2024-01-18 10:23:45 +01:00
Guillaume Lours
0d895a23f8 Merge pull request #11363 from glours/remove-watch-from-alpha
remove watch subcommand from the alpha command
2024-01-18 10:23:08 +01:00
Guillaume Lours
7cdc7e15e3 remove watch command from the alpha command
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-01-18 10:14:43 +01:00
Guillaume Lours
fb6d92250c Merge pull request #11361 from laurazard/always-handle-signals
signals/utils: always handle received signals
2024-01-18 10:14:27 +01:00
dependabot[bot]
fb026543f2 build(deps): bump github.com/docker/cli
Bumps [github.com/docker/cli](https://github.com/docker/cli) from 25.0.0-rc.2+incompatible to 25.0.0-rc.3+incompatible.
- [Commits](https://github.com/docker/cli/compare/v25.0.0-rc.2...v25.0.0-rc.3)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 09:05:40 +00:00
Milas Bowman
d688d3bf22 fix(tracing): batch span exports to prevent blocking
This was a bad configuration (my fault) that meant each span was
exported synchronously, as it ended. That can cause weird behavior
such as stuttering/blocking.

There's really no reason to NOT use the batch processor, it's the
recommended way to configure it. In the future, it might make sense
to tune the intervals based on the fact that Compose is a CLI vs
a long-running server app, but we handle flushing out on exit
already, so it's not a huge deal.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-01-17 21:17:16 +01:00
Laura Brehm
898e1b605d signals/utils: always handle received signals
The changes in
dcbf005fe4
fixed the "cancellable context" detection, and made it so that Compose
would conditionally set up signal handling when the context was already
not cancellable/when the plugin was running through the CLI, as we'd
introduced a mechanism into the CLI to signal plugins to exit through a
socket instead of handling signals themselves.

This had some (not noticed at the time) issues when running through the
CLI as, due to sharing a process group id with the parent CLI process,
when a user CTRL-Cs the CLI will notify the plugin via the socket but
the plugin process itself will also be signalled if attached to the TTY.
This impacted some Compose commands that don't set up signal handling -
so not `compose up`, but other commands would immediately quit instead
of getting some "graceful" cancelled output.

We initially attempted to address this "double notification" issue in
the CLI by executing plugins under a new pgid so that they wouldn't be
signalled, but that posed an issue with Buildx reading from the TTY,
(see: https://github.com/moby/moby/issues/47073) so we reverted the
process group id changes and ended at a temporary solution in
https://github.com/docker/cli/pull/4792 where the CLI will only notify
plugins via the socket when they are not already going to be signalled
(when attached to a TTY).

Due to this, plugins should always set up some signal handling, which
this commit implements.

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2024-01-17 17:18:20 +00:00
Nicolas De Loof
f414bf7892 fix engine version require to use healthcheck.start_interval
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-01-17 10:45:01 +01:00
Nicolas De Loof
3c4593f2ad Stop the resource timer after last expected event
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-01-16 22:18:42 +01:00
dependabot[bot]
d2562029f6 build(deps): bump github.com/containerd/containerd from 1.7.11 to 1.7.12 (#11347)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 15:13:12 -05:00
dependabot[bot]
26ed1051eb build(deps): bump github.com/docker/docker from 25.0.0-rc.1+incompatible to 25.0.0-rc.2+incompatible (#11349)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 15:12:57 -05:00
dependabot[bot]
191c10b9d0 build(deps): bump github.com/docker/cli from 25.0.0-rc.1+incompatible to 25.0.0-rc.2+incompatible (#11348)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 15:12:35 -05:00
Guillaume Lours
8b16ab1040 Merge pull request #11307 from glours/compose-go-immutable-projects
update compose-go to version using immutable Project functions
2024-01-11 14:11:12 +01:00
Guillaume Lours
24d34040e3 Merge pull request #11181 from g0t4/11153-compose-attach-override-container-attach-cmd
Implement `docker compose attach`
2024-01-11 11:11:10 +01:00
Guillaume Lours
dbe7819fd4 Merge pull request #11333 from milas/hack-user-agent
feat(cli): report more useful User-Agent on engine API requests
2024-01-11 10:57:14 +01:00
Guillaume Lours
5d05df6e5c update compose-go to version using immutable Project functions
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-01-11 10:44:42 +01:00
Milas Bowman
b621948c1b feat(cli): report more useful User-Agent on engine API requests
When using the Moby/Docker Engine API client, we do not have a
useful user agent value being reported. Ideally, in the future,
the Docker CLI will set this appropriately for plugins when it
initializes the client.

For now, manually set it, which is a bit hacky because it
requires some casting & manually invoking an option function
that's technically meant for initialization. In practice, this
is pretty safe - the cast is checked defensively and we ignore
any errors (which shouldn't be possible anyway).

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-01-10 13:38:27 -05:00
Guillaume Lours
6f62bcccbb Merge pull request #11332 from milas/bump-golangci-lint
ci(deps): bump golangci-lint to v1.55.2
2024-01-10 19:30:00 +01:00
Milas Bowman
f5c53c2d07 ci(deps): bump golangci-lint to v1.55.2
No new violations / changes needed.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2024-01-10 12:56:48 -05:00
Guillaume Lours
1cfeda71eb ci(deps): bump golang to version v1.21.6 (#11331)
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-01-10 12:18:43 -05:00
Guillaume Lours
e9c7a3a9d5 Merge pull request #11324 from docker/dependabot/go_modules/golang.org/x/sys-0.16.0
build(deps): bump golang.org/x/sys from 0.15.0 to 0.16.0
2024-01-10 15:50:30 +01:00
Brian Goff
2bf2b22fbe Add source policies for build
Build{x,kit} support passing in source policies via an (expirimental)
env var.
This change adds those policies to the build request.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2024-01-10 11:41:03 +01:00
Guillaume Lours
8d81b87513 Merge pull request #11330 from ndeloof/watch_tar
watch: remove requirements for tar binary and for sync target to be rw
2024-01-09 16:58:38 +01:00
Nicolas De Loof
575f2ed7f2 watch: remove requirements for tar binary and for sync target to be rw
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-01-09 15:43:34 +01:00
Wes Higbee
5f4b22ed7c make docs
Signed-off-by: Wes Higbee <wes.mcclure@gmail.com>
2024-01-08 17:21:26 -06:00
Wes Higbee
dcf6bd779f make mocks
Signed-off-by: Wes Higbee <wes.mcclure@gmail.com>
2024-01-08 17:15:11 -06:00
Wes Higbee
80823b77ef go ahead and wire up sig-proxy and no-stdin for consistency with underlying docker container attach
Signed-off-by: Wes Higbee <wes.mcclure@gmail.com>
2024-01-08 17:15:11 -06:00
Wes Higbee
2c16e16db7 docker compose attach via RunAttach (from docker/cli's docker container attach)
Signed-off-by: Wes Higbee <wes.mcclure@gmail.com>
2024-01-08 17:14:49 -06:00
dependabot[bot]
d1be9caf59 build(deps): bump golang.org/x/sys from 0.15.0 to 0.16.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/sys/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-08 09:34:40 +00:00
Guillaume Lours
f659918743 Merge pull request #11298 from ndeloof/proxy
remove ServiceProxy which was introduced for archived compose-cli
2024-01-08 10:04:00 +01:00
dependabot[bot]
c3c0cf3d94 build(deps): bump golang.org/x/sync from 0.5.0 to 0.6.0 (#11317)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.5.0 to 0.6.0.
- [Commits](https://github.com/golang/sync/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-05 13:43:38 -05:00
Milas Bowman
eec822de8f Merge pull request #11321 from thaJeztah/gha_bump_cli_version
gha: update DOCKER_CLI_VERSION to v24.0.7
2024-01-05 13:42:29 -05:00
Milas Bowman
6df3886b44 Merge pull request #11320 from thaJeztah/bump_engine3
go.mod: update docker/docker and docker/cli to v25.0.0-rc.1
2024-01-05 13:41:33 -05:00
Sebastiaan van Stijn
279874158c gha: update DOCKER_CLI_VERSION to v24.0.7
I noticed that the CLI was still on 20.10, but the daemon on 24.0.7;

    Docker info
    /usr/bin/docker version
    Client:
    Version:           20.10.17
    API version:       1.41
    Go version:        go1.17.11
    Git commit:        100c701
    Built:             Mon Jun  6 22:56:42 2022
    OS/Arch:           linux/amd64
    Context:           default
    Experimental:      true
    Server: Docker Engine - Community
    Engine:
    Version:          24.0.7
    API version:      1.43 (minimum version 1.12)
    Go version:       go1.20.10
    Git commit:       311b9ff
    Built:            Thu Oct 26 09:07:41 2023
    OS/Arch:          linux/amd64
    Experimental:     false
    containerd:
    Version:          1.6.26
    GitCommit:        3dd1e886e55dd695541fdcd67420c2888645a495
    runc:
    Version:          1.1.10
    GitCommit:        v1.1.10-0-g18a0cb0
    docker-init:
    Version:          0.19.0
    GitCommit:        de40ad0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-05 19:32:23 +01:00
Sebastiaan van Stijn
566d2207f3 go.mod: github.com/docker/cli v25.0.0-rc.1
full diff: https://github.com/docker/cli/compare/v25.0.0-beta.3...v25.0.0-rc.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-05 18:57:57 +01:00
Sebastiaan van Stijn
d09c39dced go.mod: github.com/docker/docker v25.0.0-rc.1
full diff: https://github.com/docker/docker/compare/v25.0.0-beta.3...v25.0.0-rc.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-05 18:57:15 +01:00
Sebastiaan van Stijn
a1d36379a3 go.mod: github.com/klauspost/compress v1.17.4
full diff: https://github.com/klauspost/compress/compare/v1.17.2...v1.17.4

v1.17.4:

- huff0: Speed up symbol counting
- huff0: Remove byteReader
- gzhttp: Allow overriding decompression on transport
- gzhttp: Clamp compression level
- gzip: Error out if reserved bits are set

v1.17.3:

- fse: Fix max header size
- zstd: Improve better/best compression
- gzhttp: Fix missing content type on Close

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-05 18:45:31 +01:00
Sebastiaan van Stijn
0c55998b41 go.mod: github.com/felixge/httpsnoop v1.0.4
full diff: https://github.com/felixge/httpsnoop/compare/v1.0.3...v1.0.4

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-05 18:39:58 +01:00
Sebastiaan van Stijn
2f6ec9b777 go.mod: github.com/docker/go-connections v0.5.0
no diff, as the tag is the same commit as we used already;
https://github.com/docker/go-connections/compare/fa09c952e3ea...v0.5.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-01-05 18:33:26 +01:00
Milas Bowman
06af729dc8 Merge pull request #11292 from laurazard/update-cli-signal-handling
Up: teardown when command context is cancelled
2024-01-02 15:48:14 -05:00
Laura Brehm
dcbf005fe4 up: gracefully teardown when command ctx cancelled
Previously, if a long-lived plugin process (such as
an execution of `compose up`) was running and then
detached from a terminal, signalling the parent CLI
process to exit would leave the plugin process behind.

To address this, changes were introduced on the CLI side
(see: https://github.com/docker/cli/pull/4599) to enable
the CLI to notify a running plugin process that it should
exit. This makes it so that, when the parent CLI process
is going to exit, the command context of the plugin
command being executed is cancelled.

This commit takes advantage of these changes by tapping into
the command context's done channel and using it to teardown
on an up.

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2023-12-23 02:49:27 +00:00
Nicolas De Loof
e105f16527 introduce stats command
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-22 16:03:02 +01:00
Laura Brehm
ce5a0c656f Fix cancellable context detection in AdaptCmd
`AdaptCmd` was previously checking for a `.WithCancel` suffix
on context strings, however it's possible for a context to be
cancellable without ending in that suffix, such as when
`context.WithValue` was called after `WithContext`, e.g.:

```go
context.Background.WithCancel.WithValue(type trace.traceContextKeyType,
val <not Stringer>).WithValue(type api.DryRunKey, val <not Stringer>)
```

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2023-12-22 13:39:04 +00:00
Nicolas De Loof
f58f23a6a2 remove ServiceProxy which was introduced for archived compose-cli
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-22 14:02:21 +01:00
Guillaume Lours
d82a1a5a03 Merge pull request #11294 from thaJeztah/bump_engine2
go.mod: docker/docker and docker/cli v25.0.0-beta.3
2023-12-22 11:28:37 +01:00
Sebastiaan van Stijn
9aa5232601 go.mod: docker/docker and docker/cli v25.0.0-beta.3
- https://github.com/docker/cli/compare/70216b662dc4...v25.0.0-beta.3
- https://github.com/docker/docker/compare/v25.0.0-beta.2...v25.0.0-beta.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-12-22 11:18:43 +01:00
Sebastiaan van Stijn
ccd83b8a74 go.mod: github.com/gorilla/mux v1.8.1
full diff: https://github.com/gorilla/mux/compoare/v1.8.0...v1.8.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-12-22 11:18:43 +01:00
Sebastiaan van Stijn
9e57850c16 go.mod: github.com/docker/distribution v2.8.3
full diff: https://github.com/docker/distribution/compare/v2.8.2...v2.8.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-12-22 11:18:43 +01:00
Sebastiaan van Stijn
35d3a7ca56 go.mod: golang.org/x/crypto v0.17.0
update the package, which contains a fix in the ssh package.

full diff: https://github.com/golang/crypto/compare/v0.16.0...v0.17.0

from the security mailing:

> Hello gophers,
>
> Version v0.17.0 of golang.org/x/crypto fixes a protocol weakness in the
> golang.org/x/crypto/ssh package that allowed a MITM attacker to compromise
> the integrity of the secure channel before it was established, allowing
> them to prevent transmission of a number of messages immediately after
> the secure channel was established without either side being aware.
>
> The impact of this attack is relatively limited, as it does not compromise
> confidentiality of the channel. Notably this attack would allow an attacker
> to prevent the transmission of the SSH2_MSG_EXT_INFO message, disabling a
> handful of newer security features.
>
> This protocol weakness was also fixed in OpenSSH 9.6.
>
> Thanks to Fabian Bäumer, Marcus Brinkmann, and Jörg Schwenk from Ruhr
> University Bochum for reporting this issue.
>
> This is CVE-2023-48795 and Go issue https://go.dev/issue/64784.
>
> Cheers,
> Roland on behalf of the Go team

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-12-22 11:18:43 +01:00
Sebastiaan van Stijn
6c998602bb go.mod: golang.org/x/crypto v0.16.0
full diff: https://github.com/golang/crypto/compare/v0.14.0...v0.16.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-12-22 11:18:43 +01:00
Sebastiaan van Stijn
402f368830 go.mod: golang.org/x/text v0.14.0
full diff: https://github.com/golang/text/compare/v0.13.0...v0.14.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-12-22 11:18:43 +01:00
Sebastiaan van Stijn
30dd3e66d7 go.mod: golang.org/x/term v0.15.0
full diff: https://github.com/golang/term/compare/v0.13.0...v0.15.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-12-22 11:18:43 +01:00
Nicolas De Loof
0c4fa017b9 Bump compose-go v2-beta.2
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-22 11:16:13 +01:00
dependabot[bot]
b12e23b0bd build(deps): bump go.uber.org/mock from 0.3.0 to 0.4.0
Bumps [go.uber.org/mock](https://github.com/uber/mock) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/uber/mock/releases)
- [Changelog](https://github.com/uber-go/mock/blob/main/CHANGELOG.md)
- [Commits](https://github.com/uber/mock/compare/v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: go.uber.org/mock
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-21 14:52:59 +01:00
Nicolas De Loof
17da54da20 introduce build --with-dependencies
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-20 15:58:54 +01:00
horus
1baa4f4489 up: fix write/close race condition in logPrinter
The code used an atomic bool to guard channel writes. However, this
failed to synchronize with the call to close(), causing a panic.

Fix the race condition by using a mutex to guard the update to the
bool `stopped` and subsequent channel writes. This ensures atomic
execution of both updates to `stopped` and channel writes, preventing
races between writes and close().

Signed-off-by: horus <horus.li@gmail.com>
2023-12-20 15:45:12 +01:00
Guillaume Lours
aefc2a111a Merge pull request #11283 from laurazard/update-cli-version-go
deps: update docker/cli to fix go version selection issue
2023-12-19 15:26:24 +01:00
Laura Brehm
7781b7c992 deps: update docker/cli to fix go version selection issue
see: 70216b662d

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2023-12-19 14:15:16 +00:00
Albin Kerouanton
785835b1a2 Add support for endpoint-specific MAC address
Related to:

- https://github.com/compose-spec/compose-spec/pull/435
- https://github.com/moby/moby/pull/45905

Since API v1.44, Moby supports a per-endpoint MAC address and returns a
warning when the container-wide mac_address field is set.

A corresponding field has been added to compose-spec and compose-go, so
we need to leverage it to set the right API field.

This commit is backward-compatible with compose files that still set the
container-wide mac_address field, and older API versions that don't know
about the endpoint-specific MAC address field.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2023-12-18 12:04:45 +01:00
Nicolas De Loof
e4fb5545f0 build do not require environment to be reslved
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-14 11:21:46 +01:00
Nicolas De Loof
74cc091225 github.com/golang/mock is deprecated
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-13 14:47:39 +01:00
Nicolas De Loof
5e61c62ecf collect services to build using WithServices
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-07 17:05:42 +01:00
Nicolas De Loof
fb3868ffaf add support for start_interval
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-07 15:59:22 +01:00
Guillaume Lours
30e80d2440 Merge pull request #11251 from ndeloof/completion_disabled
include disabled services for shell completion
2023-12-06 09:47:00 +01:00
Nicolas De Loof
bdbda79043 include disabled services for shell completion
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-06 09:38:11 +01:00
Guillaume Lours
862f2a19f4 Merge pull request #11249 from glours/bump-golang-1.21.5
bump golang to version 1.21.5
2023-12-06 09:37:18 +01:00
Guillaume Lours
ae4fd7916c bump golang to version 1.21.5
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-12-06 00:04:15 +01:00
Nicolas De Loof
26aca867d8 avoid use of service.Name when iterating on project.Services
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-05 18:54:31 +01:00
Nicolas De Loof
138facea62 project.Services is a map
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-05 18:54:31 +01:00
Nicolas De Loof
cda04f288e adopt compose-go/v2
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-05 18:54:31 +01:00
Milas Bowman
85a1aec123 regen docs
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-12-05 18:08:38 +01:00
Milas Bowman
9c29d2236d use custom config type for OCI v1.0
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-12-05 18:08:38 +01:00
Milas Bowman
df6fe59f72 tweak help message on oci version flag
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-12-05 18:08:38 +01:00
Milas Bowman
07df9cc46e fix typo
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-12-05 18:08:38 +01:00
Milas Bowman
7c8ff36d78 move around OCI logic, auto fallback/retry 1.1 -> 1.0
Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-12-05 18:08:38 +01:00
Milas Bowman
111ad3b039 fix(publish): add OCI 1.0 fallback support for AWS ECR
Currently, we publish Compose artifacts following the OCI 1.1
specification, which is still in the RC state.

As a result, not all registries support it yet. Most notably,
AWS ECR will reject certain OCI 1.1-compliant requests with
`405 Method Not Supported` with cryptic `Invalid JSON` errors.

This adds initial support for Compose to generate either an
OCI 1.0 or OCI 1.1 compatible manifest. Notably, the OCI 1.0
manifest will be missing the `application/vnd.docker.compose.project`
artifact type, as that does not exist in that version of the
spec. (Less importantly, it uses an empty `ImageConfig`
instead of the newer `application/vnd.oci.empty.v1+json` media
type for the config.)

Currently, this is not exposed as an option (via CLI flags or
env vars). By default, OCI 1.1 is used unless the registry
domain is `amazonaws.com`, which indicates an ECR registry, so
Compose will instead use OCI 1.0.

Moving forward, we should decide how much we want to expose/
support different OCI versions and investigate if there's a
more generic way to feature probe the registry to avoid
maintaining a hardcoded list of domains, which is both tedious
and insufficient.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-12-05 18:08:38 +01:00
Nicolas De Loof
8026d0e2f2 adopt container.RestartPolicy*
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-05 17:02:37 +01:00
Nicolas De Loof
df1533a1ca [lint] don't use deprecated types
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-05 17:02:37 +01:00
Nicolas De Loof
8639fbae86 go mod tidy
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-05 17:02:37 +01:00
Wes Higbee
56e2ad9ee5 update to v1.25 for RunAttach
Signed-off-by: Wes Higbee <wes.mcclure@gmail.com>
2023-12-05 17:02:37 +01:00
Nicolas De Loof
ce1ddb6c7e fix combination of --pull always --no-build
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-12-04 11:08:08 +01:00
dependabot[bot]
c5824702bf build(deps): bump golang.org/x/sys from 0.14.0 to 0.15.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.14.0 to 0.15.0.
- [Commits](https://github.com/golang/sys/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-30 09:42:39 +01:00
vyneer
1f148244af send out a cancel event on SIGINT/SIGTERM
Signed-off-by: vyneer <vyn33r@gmail.com>
2023-11-30 09:11:55 +01:00
johnthagen
9faef4aebb Update README.md to use standard compose.yaml file name
Signed-off-by: johnthagen <johnthagen@users.noreply.github.com>
2023-11-30 08:53:44 +01:00
Nicolas De Loof
59f11ecbeb Fix configs are mounted under /<id>
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-29 16:53:22 +01:00
Amit Saha
750553c866 introduce compose logs --index to select a replica container
Signed-off-by: Amit Saha <asaha@atlassian.com>
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-29 13:56:16 +01:00
Amit Saha
8c964f5ad3 Update E2E test
Signed-off-by: Amit Saha <asaha@atlassian.com>
2023-11-29 13:56:16 +01:00
Amit Saha
90ca13b747 Fix E2E test to have index in the correct position
Signed-off-by: Amit Saha <asaha@atlassian.com>
2023-11-29 13:56:16 +01:00
Amit Saha
f9946127ce Fix docs
Signed-off-by: Amit Saha <asaha@atlassian.com>
2023-11-29 13:56:16 +01:00
Amit Saha
ddda59a130 Add index option to compose logs command
Signed-off-by: Amit Saha <asaha@atlassian.com>
2023-11-29 13:56:16 +01:00
Amit Saha
e981c35863 Add failing test
Signed-off-by: Amit Saha <asaha@atlassian.com>
2023-11-29 13:56:16 +01:00
Nicolas De Loof
16c4241c0b log we don't expose service ports when --verbose
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-29 11:40:16 +01:00
Guillaume Lours
f5e3ff03f0 Merge pull request #11225 from ndeloof/ddev-bump
bump ddev to 1.22.4
2023-11-27 14:29:36 +01:00
Nicolas De Loof
9025d63a63 bump ddev
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-27 14:19:53 +01:00
Nicolas De Loof
a1de0b96c3 Restore Project is ps json output
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-24 10:46:33 +01:00
Guillaume Lours
ba24a656bf Merge pull request #11220 from ndeloof/ps_profile
Introduce ps --orphans to include/exclude services not declared by project
2023-11-23 13:52:20 +01:00
Nicolas De Loof
caa0cbbc4b Introduce ps --orphans so user can include/exclude services not declared by project
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-23 13:43:49 +01:00
Guillaume Lours
8c0c5cb671 Merge pull request #11219 from ndeloof/no_answer
let contributor know we might close unanswered issues
2023-11-23 11:28:04 +01:00
Nicolas De Loof
29e9fdba16 let contributor know we might close unanswered issues
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-11-23 11:06:31 +01:00
Guillaume Lours
c665c53cc1 bump buildx to v0.12.0 and adapt code to changes
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2023-11-23 07:36:13 +01:00
223 changed files with 5787 additions and 3355 deletions

View File

@@ -18,9 +18,6 @@ on:
required: false
default: "false"
env:
DOCKER_CLI_VERSION: "20.10.17"
permissions:
contents: read # to fetch code (actions/checkout)
@@ -129,7 +126,12 @@ jobs:
name: coverage-data-unit
path: bin/coverage/unit/
if-no-files-found: error
-
name: Unit Test Summary
uses: test-summary/action@v2
with:
paths: bin/coverage/unit/report.xml
if: always()
e2e:
runs-on: ubuntu-latest
strategy:
@@ -138,10 +140,21 @@ jobs:
mode:
- plugin
- standalone
engine:
- 24.0.9
- 25.0.4
- 26.0.0
steps:
-
name: Checkout
uses: actions/checkout@v3
- name: Install Docker ${{ matrix.engine }}
run: |
sudo apt-get install curl
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh ./get-docker.sh --version ${{ matrix.engine }}
- name: Check Docker Version
run: docker --version
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -152,11 +165,6 @@ jobs:
go-version-file: 'go.mod'
check-latest: true
cache: true
-
name: Setup docker CLI
run: |
curl https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_CLI_VERSION}.tgz | tar xz
sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version
-
name: Build
uses: docker/bake-action@v2
@@ -197,7 +205,12 @@ jobs:
rm -f /usr/local/bin/docker-compose
cp bin/build/docker-compose /usr/local/bin
make e2e-compose-standalone
-
name: e2e Test Summary
uses: test-summary/action@v2
with:
paths: /tmp/report/report.xml
if: always()
coverage:
runs-on: ubuntu-22.04
needs:

View File

@@ -28,14 +28,14 @@ jobs:
uses: actions/checkout@v4
-
name: Upload reference YAML docs
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: docs-yaml
path: docs/reference
retention-days: 1
validate:
uses: docker/docs/.github/workflows/validate-upstream.yml@main
uses: docker/docs/.github/workflows/validate-upstream.yml@919a9b9104a34a40b30d116529bcce589a544d1c # pin for artifact v4 support: https://github.com/docker/docs/pull/19220
needs:
- docs-yaml
with:

View File

@@ -66,6 +66,11 @@ When sending lengthy log files, consider posting them as a gist
Don't forget to remove sensitive data from your log files before posting (you
can replace those parts with "REDACTED").
_Note:_
Maintainers might request additional information to diagnose an issue,
if initial reporter doesn't answer within a reasonable delay (a few weeks),
issue will be closed.
## Quick contribution tips and guidelines
This section gives the experienced contributor some tips and guidelines.

View File

@@ -15,9 +15,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
ARG GO_VERSION=1.21.4
ARG GO_VERSION=1.21.8
ARG XX_VERSION=1.2.1
ARG GOLANGCI_LINT_VERSION=v1.54.2
ARG GOLANGCI_LINT_VERSION=v1.55.2
ARG ADDLICENSE_VERSION=v1.0.0
ARG BUILD_TAGS="e2e"
@@ -101,16 +101,20 @@ RUN --mount=type=bind,target=. \
FROM build-base AS test
ARG CGO_ENABLED=0
ARG BUILD_TAGS
ENV COMPOSE_MENU=FALSE
RUN --mount=type=bind,target=. \
--mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/go/pkg/mod \
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" && \
rm -rf /tmp/report && \
mkdir -p /tmp/report && \
go run gotest.tools/gotestsum@latest --format testname --junitfile "/tmp/report/report.xml" -- -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 --link /tmp/coverage /
COPY --from=test --link /tmp/report /
FROM base AS license-set
ARG LICENSE_FILES

View File

@@ -24,7 +24,6 @@
people = [
"glours",
"milas",
"laurazard",
"ndeloof",
"nicksieger",
"StefanScherer",
@@ -39,6 +38,7 @@
"aiordache",
"chris-crone",
"gtardif",
"laurazard",
"maxcleme",
"rumpl",
"thaJeztah"

View File

@@ -13,6 +13,7 @@
# limitations under the License.
PKG := github.com/docker/compose/v2
export COMPOSE_MENU = FALSE
VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags)
GO_LDFLAGS ?= -w -X ${PKG}/internal.Version=${VERSION}
@@ -75,11 +76,11 @@ install: binary
.PHONY: e2e-compose
e2e-compose: ## Run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test
go test -v $(TEST_FLAGS) -count=1 ./pkg/e2e
go run gotest.tools/gotestsum@latest --format testname --junitfile "/tmp/report/report.xml" -- -v $(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
go test $(TEST_FLAGS) -v -count=1 -parallel=1 --tags=standalone ./pkg/e2e
go run gotest.tools/gotestsum@latest --format testname --junitfile "/tmp/report/report.xml" -- $(TEST_FLAGS) -v -count=1 -parallel=1 --tags=standalone ./pkg/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
@@ -89,7 +90,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 --version >/dev/null 2>&1 || go install go.uber.org/mock/mockgen@v0.3.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

View File

@@ -52,7 +52,7 @@ Quick Start
Using Docker Compose is a three-step process:
1. Define your app's environment with a `Dockerfile` so it can be
reproduced anywhere.
2. Define the services that make up your app in `docker-compose.yml` so
2. Define the services that make up your app in `compose.yaml` so
they can be run together in an isolated environment.
3. Lastly, run `docker compose up` and Compose will start and run your entire
app.

View File

@@ -104,7 +104,7 @@ func wrapRunE(c *cobra.Command, cmdSpan trace.Span, tracingShutdown tracing.Shut
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)
ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
defer cancel()
// TODO(milas): add an env var to enable logging from the
// OTel components for debugging purposes

View File

@@ -31,7 +31,6 @@ func alphaCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
},
}
cmd.AddCommand(
watchCommand(p, dockerCli, backend),
vizCommand(p, dockerCli, backend),
publishCommand(p, dockerCli, backend),
)

80
cmd/compose/attach.go Normal file
View File

@@ -0,0 +1,80 @@
/*
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/docker/cli/cli/command"
"github.com/docker/compose/v2/pkg/api"
"github.com/spf13/cobra"
)
type attachOpts struct {
*composeOptions
service string
index int
detachKeys string
noStdin bool
proxy bool
}
func attachCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
opts := attachOpts{
composeOptions: &composeOptions{
ProjectOptions: p,
},
}
runCmd := &cobra.Command{
Use: "attach [OPTIONS] SERVICE",
Short: "Attach local standard input, output, and error streams to a service's running container",
Args: cobra.MinimumNArgs(1),
PreRunE: Adapt(func(ctx context.Context, args []string) error {
opts.service = args[0]
return nil
}),
RunE: Adapt(func(ctx context.Context, args []string) error {
return runAttach(ctx, dockerCli, backend, opts)
}),
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
runCmd.Flags().IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas.")
runCmd.Flags().StringVarP(&opts.detachKeys, "detach-keys", "", "", "Override the key sequence for detaching from a container.")
runCmd.Flags().BoolVar(&opts.noStdin, "no-stdin", false, "Do not attach STDIN")
runCmd.Flags().BoolVar(&opts.proxy, "sig-proxy", true, "Proxy all received signals to the process")
return runCmd
}
func runAttach(ctx context.Context, dockerCli command.Cli, backend api.Service, opts attachOpts) error {
projectName, err := opts.toProjectName(ctx, dockerCli)
if err != nil {
return err
}
attachOpts := api.AttachOptions{
Service: opts.service,
Index: opts.index,
DetachKeys: opts.detachKeys,
NoStdin: opts.noStdin,
Proxy: opts.proxy,
}
return backend.Attach(ctx, projectName, attachOpts)
}

View File

@@ -22,13 +22,12 @@ import (
"os"
"strings"
"github.com/compose-spec/compose-go/cli"
"github.com/compose-spec/compose-go/loader"
"github.com/compose-spec/compose-go/types"
buildx "github.com/docker/buildx/util/progress"
"github.com/compose-spec/compose-go/v2/cli"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
cliopts "github.com/docker/cli/opts"
ui "github.com/docker/compose/v2/pkg/progress"
buildkit "github.com/moby/buildkit/util/progress/progressui"
"github.com/spf13/cobra"
"github.com/docker/compose/v2/pkg/api"
@@ -44,13 +43,21 @@ type buildOptions struct {
memory cliopts.MemBytes
ssh string
builder string
deps bool
}
func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions, error) {
var SSHKeys []types.SSHKey
var err error
if opts.ssh != "" {
SSHKeys, err = loader.ParseShortSSHSyntax(opts.ssh)
id, path, found := strings.Cut(opts.ssh, "=")
if !found && id != "default" {
return api.BuildOptions{}, fmt.Errorf("invalid ssh key %q", opts.ssh)
}
SSHKeys = append(SSHKeys, types.SSHKey{
ID: id,
Path: path,
})
if err != nil {
return api.BuildOptions{}, err
}
@@ -68,6 +75,7 @@ func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions,
NoCache: opts.noCache,
Quiet: opts.quiet,
Services: services,
Deps: opts.deps,
SSHs: SSHKeys,
Builder: builderName,
}, nil
@@ -102,30 +110,33 @@ func buildCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}),
ValidArgsFunction: completeServiceNames(dockerCli, 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().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")
cmd.Flags().MarkHidden("compress") //nolint:errcheck
cmd.Flags().Bool("force-rm", true, "Always remove intermediate containers. DEPRECATED")
cmd.Flags().MarkHidden("force-rm") //nolint:errcheck
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().VarP(&opts.memory, "memory", "m", "Set memory limit for the build container. Not supported by BuildKit.")
cmd.Flags().StringVar(&p.Progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of ui output (%s)`, strings.Join(printerModes, ", ")))
cmd.Flags().MarkHidden("progress") //nolint:errcheck
flags := cmd.Flags()
flags.BoolVar(&opts.push, "push", false, "Push service images")
flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Don't print anything to STDOUT")
flags.BoolVar(&opts.pull, "pull", false, "Always attempt to pull a newer version of the image")
flags.StringArrayVar(&opts.args, "build-arg", []string{}, "Set build-time variables for services")
flags.StringVar(&opts.ssh, "ssh", "", "Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent)")
flags.StringVar(&opts.builder, "builder", "", "Set builder to use")
flags.BoolVar(&opts.deps, "with-dependencies", false, "Also build dependencies (transitively)")
flags.Bool("parallel", true, "Build images in parallel. DEPRECATED")
flags.MarkHidden("parallel") //nolint:errcheck
flags.Bool("compress", true, "Compress the build context using gzip. DEPRECATED")
flags.MarkHidden("compress") //nolint:errcheck
flags.Bool("force-rm", true, "Always remove intermediate containers. DEPRECATED")
flags.MarkHidden("force-rm") //nolint:errcheck
flags.BoolVar(&opts.noCache, "no-cache", false, "Do not use cache when building the image")
flags.Bool("no-rm", false, "Do not remove intermediate containers after a successful build. DEPRECATED")
flags.MarkHidden("no-rm") //nolint:errcheck
flags.VarP(&opts.memory, "memory", "m", "Set memory limit for the build container. Not supported by BuildKit.")
flags.StringVar(&p.Progress, "progress", string(buildkit.AutoMode), fmt.Sprintf(`Set type of ui output (%s)`, strings.Join(printerModes, ", ")))
flags.MarkHidden("progress") //nolint:errcheck
return cmd
}
func runBuild(ctx context.Context, dockerCli command.Cli, backend api.Service, opts buildOptions, services []string) error {
project, err := opts.ToProject(dockerCli, services, cli.WithResolvedPaths(true))
project, _, err := opts.ToProject(ctx, dockerCli, services, cli.WithResolvedPaths(true), cli.WithoutEnvironmentResolution)
if err != nil {
return err
}

View File

@@ -37,17 +37,18 @@ func noCompletion() validArgsFn {
func completeServiceNames(dockerCli command.Cli, p *ProjectOptions) validArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
p.Offline = true
project, err := p.ToProject(dockerCli, nil)
project, _, err := p.ToProject(cmd.Context(), dockerCli, nil)
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}
var serviceNames []string
for _, s := range project.ServiceNames() {
var values []string
serviceNames := append(project.ServiceNames(), project.DisabledServiceNames()...)
for _, s := range serviceNames {
if toComplete == "" || strings.HasPrefix(s, toComplete) {
serviceNames = append(serviceNames, s)
values = append(values, s)
}
}
return serviceNames, cobra.ShellCompDirectiveNoFileComp
return values, cobra.ShellCompDirectiveNoFileComp
}
}
@@ -72,7 +73,7 @@ func completeProjectNames(backend api.Service) func(cmd *cobra.Command, args []s
func completeProfileNames(dockerCli command.Cli, p *ProjectOptions) validArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
p.Offline = true
project, err := p.ToProject(dockerCli, nil)
project, _, err := p.ToProject(cmd.Context(), dockerCli, nil)
if err != nil {
return nil, cobra.ShellCompDirectiveNoFileComp
}

View File

@@ -27,26 +27,29 @@ import (
"strings"
"syscall"
"github.com/compose-spec/compose-go/cli"
"github.com/compose-spec/compose-go/dotenv"
"github.com/compose-spec/compose-go/types"
composegoutils "github.com/compose-spec/compose-go/utils"
"github.com/compose-spec/compose-go/v2/cli"
"github.com/compose-spec/compose-go/v2/dotenv"
"github.com/compose-spec/compose-go/v2/loader"
"github.com/compose-spec/compose-go/v2/types"
composegoutils "github.com/compose-spec/compose-go/v2/utils"
"github.com/docker/buildx/util/logutil"
buildx "github.com/docker/buildx/util/progress"
dockercli "github.com/docker/cli/cli"
"github.com/docker/cli/cli-plugins/manager"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/compose/v2/internal/desktop"
"github.com/docker/compose/v2/internal/experimental"
"github.com/docker/compose/v2/internal/tracing"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/compose"
ui "github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/remote"
"github.com/docker/compose/v2/pkg/utils"
buildkit "github.com/moby/buildkit/util/progress/progressui"
"github.com/morikuni/aec"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/compose"
ui "github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"
)
const (
@@ -62,8 +65,18 @@ const (
ComposeIgnoreOrphans = "COMPOSE_IGNORE_ORPHANS"
// ComposeEnvFiles defines the env files to use if --env-file isn't used
ComposeEnvFiles = "COMPOSE_ENV_FILES"
// ComposeMenu defines if the navigation menu should be rendered. Can be also set via --menu
ComposeMenu = "COMPOSE_MENU"
)
type Backend interface {
api.Service
SetDesktopClient(cli *desktop.Client)
SetExperiments(experiments *experimental.State)
}
// Command defines a compose CLI command as a func with args
type Command func(context.Context, []string) error
@@ -73,20 +86,17 @@ type CobraCommand func(context.Context, *cobra.Command, []string) error
// AdaptCmd adapt a CobraCommand func to cobra library
func AdaptCmd(fn CobraCommand) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
contextString := fmt.Sprintf("%s", ctx)
if !strings.HasSuffix(contextString, ".WithCancel") { // need to handle cancel
cancellableCtx, cancel := context.WithCancel(cmd.Context())
ctx = cancellableCtx
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGTERM, syscall.SIGINT)
go func() {
<-s
cancel()
signal.Stop(s)
close(s)
}()
}
ctx, cancel := context.WithCancel(cmd.Context())
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGTERM, syscall.SIGINT)
go func() {
<-s
cancel()
signal.Stop(s)
close(s)
}()
err := fn(ctx, cmd, args)
var composeErr compose.Error
if api.IsErrCanceled(err) || errors.Is(ctx.Err(), context.Canceled) {
@@ -143,14 +153,15 @@ func (o *ProjectOptions) WithServices(dockerCli command.Cli, fn ProjectServicesF
options := []cli.ProjectOptionsFn{
cli.WithResolvedPaths(true),
cli.WithDiscardEnvFile,
cli.WithContext(ctx),
}
project, err := o.ToProject(dockerCli, args, options...)
project, metrics, err := o.ToProject(ctx, dockerCli, args, options...)
if err != nil {
return err
}
ctx = context.WithValue(ctx, tracing.MetricsKey{}, metrics)
return fn(ctx, project, args)
})
}
@@ -159,19 +170,19 @@ 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.StringArrayVar(&o.EnvFiles, "env-file", nil, "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.StringVar(&o.Progress, "progress", buildx.PrinterModeAuto, fmt.Sprintf(`Set type of progress output (%s)`, strings.Join(printerModes, ", ")))
f.StringVar(&o.Progress, "progress", string(buildkit.AutoMode), fmt.Sprintf(`Set type of progress output (%s)`, strings.Join(printerModes, ", ")))
_ = f.MarkHidden("workdir")
}
func (o *ProjectOptions) projectOrName(dockerCli command.Cli, services ...string) (*types.Project, string, error) {
func (o *ProjectOptions) projectOrName(ctx context.Context, dockerCli command.Cli, services ...string) (*types.Project, string, error) {
name := o.ProjectName
var project *types.Project
if len(o.ConfigPaths) > 0 || o.ProjectName == "" {
p, err := o.ToProject(dockerCli, services, cli.WithDiscardEnvFile)
p, _, err := o.ToProject(ctx, dockerCli, services, cli.WithDiscardEnvFile)
if err != nil {
envProjectName := os.Getenv(ComposeProjectName)
if envProjectName != "" {
@@ -185,7 +196,7 @@ func (o *ProjectOptions) projectOrName(dockerCli command.Cli, services ...string
return project, name, nil
}
func (o *ProjectOptions) toProjectName(dockerCli command.Cli) (string, error) {
func (o *ProjectOptions) toProjectName(ctx context.Context, dockerCli command.Cli) (string, error) {
if o.ProjectName != "" {
return o.ProjectName, nil
}
@@ -195,45 +206,89 @@ func (o *ProjectOptions) toProjectName(dockerCli command.Cli) (string, error) {
return envProjectName, nil
}
project, err := o.ToProject(dockerCli, nil)
project, _, err := o.ToProject(ctx, dockerCli, nil)
if err != nil {
return "", err
}
return project.Name, nil
}
func (o *ProjectOptions) ToProject(dockerCli command.Cli, services []string, po ...cli.ProjectOptionsFn) (*types.Project, error) {
if !o.Offline {
po = o.configureRemoteLoaders(dockerCli, po)
func (o *ProjectOptions) ToModel(ctx context.Context, dockerCli command.Cli, services []string, po ...cli.ProjectOptionsFn) (map[string]any, error) {
remotes := o.remoteLoaders(dockerCli)
for _, r := range remotes {
po = append(po, cli.WithResourceLoader(r))
}
options, err := o.toProjectOptions(po...)
if err != nil {
return nil, compose.WrapComposeError(err)
return nil, err
}
if o.Compatibility || utils.StringToBool(options.Environment[ComposeCompatibility]) {
api.Separator = "_"
}
project, err := cli.ProjectFromOptions(options)
return options.LoadModel(ctx)
}
func (o *ProjectOptions) ToProject(ctx context.Context, dockerCli command.Cli, services []string, po ...cli.ProjectOptionsFn) (*types.Project, tracing.Metrics, error) {
var metrics tracing.Metrics
remotes := o.remoteLoaders(dockerCli)
for _, r := range remotes {
po = append(po, cli.WithResourceLoader(r))
}
options, err := o.toProjectOptions(po...)
if err != nil {
return nil, compose.WrapComposeError(err)
return nil, metrics, compose.WrapComposeError(err)
}
options.WithListeners(func(event string, metadata map[string]any) {
switch event {
case "extends":
metrics.CountExtends++
case "include":
paths := metadata["path"].(types.StringList)
for _, path := range paths {
var isRemote bool
for _, r := range remotes {
if r.Accept(path) {
isRemote = true
break
}
}
if isRemote {
metrics.CountIncludesRemote++
} else {
metrics.CountIncludesLocal++
}
}
}
})
if o.Compatibility || utils.StringToBool(options.Environment[ComposeCompatibility]) {
api.Separator = "_"
}
project, err := options.LoadProject(ctx)
if err != nil {
return nil, metrics, compose.WrapComposeError(err)
}
if project.Name == "" {
return nil, errors.New("project name can't be empty. Use `--project-name` to set a valid name")
return nil, metrics, errors.New("project name can't be empty. Use `--project-name` to set a valid name")
}
err = project.EnableServices(services...)
project, err = project.WithServicesEnabled(services...)
if err != nil {
return nil, err
return nil, metrics, err
}
for i, s := range project.Services {
for name, s := range project.Services {
s.CustomLabels = map[string]string{
api.ProjectLabel: project.Name,
api.ServiceLabel: s.Name,
api.ServiceLabel: name,
api.VersionLabel: api.ComposeVersion,
api.WorkingDirLabel: project.WorkingDir,
api.ConfigFilesLabel: strings.Join(project.ComposeFiles, ","),
@@ -242,21 +297,22 @@ func (o *ProjectOptions) ToProject(dockerCli command.Cli, services []string, po
if len(o.EnvFiles) != 0 {
s.CustomLabels[api.EnvironmentFileLabel] = strings.Join(o.EnvFiles, ",")
}
project.Services[i] = s
project.Services[name] = s
}
project.WithoutUnnecessaryResources()
project = project.WithoutUnnecessaryResources()
err = project.ForServices(services)
return project, err
project, err = project.WithSelectedServices(services)
return project, metrics, err
}
func (o *ProjectOptions) configureRemoteLoaders(dockerCli command.Cli, po []cli.ProjectOptionsFn) []cli.ProjectOptionsFn {
func (o *ProjectOptions) remoteLoaders(dockerCli command.Cli) []loader.ResourceLoader {
if o.Offline {
return nil
}
git := remote.NewGitRemoteLoader(o.Offline)
oci := remote.NewOCIRemoteLoader(dockerCli, o.Offline)
po = append(po, cli.WithResourceLoader(git), cli.WithResourceLoader(oci))
return po
return []loader.ResourceLoader{git, oci}
}
func (o *ProjectOptions) toProjectOptions(po ...cli.ProjectOptionsFn) (*cli.ProjectOptions, error) {
@@ -264,10 +320,10 @@ func (o *ProjectOptions) toProjectOptions(po ...cli.ProjectOptionsFn) (*cli.Proj
append(po,
cli.WithWorkingDirectory(o.ProjectDir),
cli.WithOsEnv,
cli.WithEnvFiles(o.EnvFiles...),
cli.WithDotEnv,
cli.WithConfigFileEnv,
cli.WithDefaultConfigPath,
cli.WithEnvFiles(o.EnvFiles...),
cli.WithDotEnv,
cli.WithDefaultProfiles(o.Profiles...),
cli.WithName(o.ProjectName))...)
}
@@ -281,7 +337,7 @@ func RunningAsStandalone() bool {
}
// RootCommand returns the compose command with its child commands
func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //nolint:gocyclo
func RootCommand(dockerCli command.Cli, backend Backend) *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
@@ -292,6 +348,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
"commandConn.CloseRead:",
))
experiments := experimental.NewState()
opts := ProjectOptions{}
var (
ansi string
@@ -303,7 +360,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
)
c := &cobra.Command{
Short: "Docker Compose",
Long: "Define and run multi-container applications with Docker.",
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) !
@@ -321,11 +378,17 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
}
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
// (1) process env vars
err := setEnvWithDotEnv(&opts)
if err != nil {
return err
}
parent := cmd.Root()
// (2) call parent pre-run
// TODO(milas): this seems incorrect, remove or document
if parent != nil {
parentPrerun := parent.PersistentPreRunE
if parentPrerun != nil {
@@ -335,6 +398,11 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
}
}
}
// (3) set up display/output
if verbose {
logrus.SetLevel(logrus.TraceLevel)
}
if noAnsi {
if ansi != "auto" {
return errors.New(`cannot specify DEPRECATED "--no-ansi" and "--ansi". Please use only "--ansi"`)
@@ -342,14 +410,9 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
ansi = "never"
fmt.Fprint(os.Stderr, "option '--no-ansi' is DEPRECATED ! Please use '--ansi' instead.\n")
}
if verbose {
logrus.SetLevel(logrus.TraceLevel)
}
if v, ok := os.LookupEnv("COMPOSE_ANSI"); ok && !cmd.Flags().Changed("ansi") {
ansi = v
}
formatter.SetANSIMode(dockerCli, ansi)
if noColor, ok := os.LookupEnv("NO_COLOR"); ok && noColor != "" {
@@ -367,6 +430,9 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
switch opts.Progress {
case ui.ModeAuto:
ui.Mode = ui.ModeAuto
if ansi == "never" {
ui.Mode = ui.ModePlain
}
case ui.ModeTTY:
if ansi == "never" {
return fmt.Errorf("can't use --progress tty while ANSI support is disabled")
@@ -383,6 +449,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
return fmt.Errorf("unsupported --progress value %q", opts.Progress)
}
// (4) options validation / normalization
if opts.WorkDir != "" {
if opts.ProjectDir != "" {
return errors.New(`cannot specify DEPRECATED "--workdir" and "--project-directory". Please use only "--project-directory" instead`)
@@ -419,19 +486,44 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
parallel = i
}
if parallel > 0 {
logrus.Debugf("Limiting max concurrency to %d jobs", parallel)
backend.MaxConcurrency(parallel)
}
ctx, err := backend.DryRunMode(cmd.Context(), dryRun)
// (5) dry run detection
ctx, err = backend.DryRunMode(ctx, dryRun)
if err != nil {
return err
}
cmd.SetContext(ctx)
// (6) Desktop integration
var desktopCli *desktop.Client
if !dryRun {
if desktopCli, err = desktop.NewFromDockerClient(ctx, dockerCli); desktopCli != nil {
logrus.Debugf("Enabled Docker Desktop integration (experimental) @ %s", desktopCli.Endpoint())
backend.SetDesktopClient(desktopCli)
} else if err != nil {
// not fatal, Compose will still work but behave as though
// it's not running as part of Docker Desktop
logrus.Debugf("failed to enable Docker Desktop integration: %v", err)
} else {
logrus.Trace("Docker Desktop integration not enabled")
}
}
// (7) experimental features
if err := experiments.Load(ctx, desktopCli); err != nil {
logrus.Debugf("Failed to query feature flags from Desktop: %v", err)
}
backend.SetExperiments(experiments)
return nil
},
}
c.AddCommand(
upCommand(&opts, dockerCli, backend),
upCommand(&opts, dockerCli, backend, experiments),
downCommand(&opts, dockerCli, backend),
startCommand(&opts, dockerCli, backend),
restartCommand(&opts, dockerCli, backend),
@@ -439,11 +531,12 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
psCommand(&opts, dockerCli, backend),
listCommand(dockerCli, backend),
logsCommand(&opts, dockerCli, backend),
configCommand(&opts, dockerCli, backend),
configCommand(&opts, dockerCli),
killCommand(&opts, dockerCli, backend),
runCommand(&opts, dockerCli, backend),
removeCommand(&opts, dockerCli, backend),
execCommand(&opts, dockerCli, backend),
attachCommand(&opts, dockerCli, backend),
pauseCommand(&opts, dockerCli, backend),
unpauseCommand(&opts, dockerCli, backend),
topCommand(&opts, dockerCli, backend),
@@ -458,6 +551,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command { //
copyCommand(&opts, dockerCli, backend),
waitCommand(&opts, dockerCli, backend),
scaleCommand(&opts, dockerCli, backend),
statsCommand(&opts, dockerCli),
watchCommand(&opts, dockerCli, backend),
alphaCommand(&opts, dockerCli, backend),
)
@@ -507,12 +601,8 @@ func setEnvWithDotEnv(prjOpts *ProjectOptions) error {
if err != nil {
return compose.WrapComposeError(err)
}
workingDir, err := options.GetWorkingDir()
if err != nil {
return err
}
envFromFile, err := dotenv.GetEnvFromFile(composegoutils.GetAsEqualsMap(os.Environ()), workingDir, options.EnvFiles)
envFromFile, err := dotenv.GetEnvFromFile(composegoutils.GetAsEqualsMap(os.Environ()), options.EnvFiles)
if err != nil {
return err
}
@@ -532,3 +622,15 @@ var printerModes = []string{
ui.ModePlain,
ui.ModeQuiet,
}
func SetUnchangedOption(name string, experimentalFlag bool) bool {
var value bool
// If the var is defined we use that value first
if envVar, ok := os.LookupEnv(name); ok {
value = utils.StringToBool(envVar)
} else {
// if not, we try to get it from experimental feature flag
value = experimentalFlag
}
return value
}

View File

@@ -19,32 +19,32 @@ package compose
import (
"testing"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"gotest.tools/v3/assert"
)
func TestFilterServices(t *testing.T) {
p := &types.Project{
Services: types.Services{
{
"foo": {
Name: "foo",
Links: []string{"bar"},
},
{
"bar": {
Name: "bar",
DependsOn: map[string]types.ServiceDependency{
"zot": {},
},
},
{
"zot": {
Name: "zot",
},
{
"qix": {
Name: "qix",
},
},
}
err := p.ForServices([]string{"bar"})
p, err := p.WithSelectedServices([]string{"bar"})
assert.NilError(t, err)
assert.Equal(t, len(p.Services), 2)

View File

@@ -19,15 +19,20 @@ package compose
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"os"
"sort"
"strings"
"github.com/compose-spec/compose-go/cli"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/cli"
"github.com/compose-spec/compose-go/v2/template"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/compose"
@@ -48,21 +53,32 @@ type configOptions struct {
images bool
hash string
noConsistency bool
variables bool
}
func (o *configOptions) ToProject(ctx context.Context, dockerCli command.Cli, services []string, po ...cli.ProjectOptionsFn) (*types.Project, error) {
po = append(po,
po = append(po, o.ToProjectOptions()...)
project, _, err := o.ProjectOptions.ToProject(ctx, dockerCli, services, po...)
return project, err
}
func (o *configOptions) ToModel(ctx context.Context, dockerCli command.Cli, services []string, po ...cli.ProjectOptionsFn) (map[string]any, error) {
po = append(po, o.ToProjectOptions()...)
return o.ProjectOptions.ToModel(ctx, dockerCli, services, po...)
}
func (o *configOptions) ToProjectOptions() []cli.ProjectOptionsFn {
return []cli.ProjectOptionsFn{
cli.WithInterpolation(!o.noInterpolate),
cli.WithResolvedPaths(!o.noResolvePath),
cli.WithNormalization(!o.noNormalize),
cli.WithConsistency(!o.noConsistency),
cli.WithDefaultProfiles(o.Profiles...),
cli.WithDiscardEnvFile,
cli.WithContext(ctx))
return o.ProjectOptions.ToProject(dockerCli, services, po...)
}
}
func configCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
func configCommand(p *ProjectOptions, dockerCli command.Cli) *cobra.Command {
opts := configOptions{
ProjectOptions: p,
}
@@ -99,18 +115,21 @@ func configCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service
if opts.images {
return runConfigImages(ctx, dockerCli, opts, args)
}
if opts.variables {
return runVariables(ctx, dockerCli, opts, args)
}
return runConfig(ctx, dockerCli, backend, opts, args)
return runConfig(ctx, dockerCli, opts, args)
}),
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
flags := cmd.Flags()
flags.StringVar(&opts.Format, "format", "yaml", "Format the output. Values: [yaml | json]")
flags.BoolVar(&opts.resolveImageDigests, "resolve-image-digests", false, "Pin image tags to digests.")
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.resolveImageDigests, "resolve-image-digests", false, "Pin image tags to digests")
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.")
@@ -118,25 +137,49 @@ func configCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service
flags.BoolVar(&opts.profiles, "profiles", false, "Print the profile names, one per line.")
flags.BoolVar(&opts.images, "images", false, "Print the image names, one per line.")
flags.StringVar(&opts.hash, "hash", "", "Print the service config hash, one per line.")
flags.BoolVar(&opts.variables, "variables", false, "Print model variables and default values.")
flags.StringVarP(&opts.Output, "output", "o", "", "Save to file (default to stdout)")
return cmd
}
func runConfig(ctx context.Context, dockerCli command.Cli, backend api.Service, opts configOptions, services []string) error {
func runConfig(ctx context.Context, dockerCli command.Cli, opts configOptions, services []string) error {
var content []byte
project, err := opts.ToProject(ctx, dockerCli, services)
if err != nil {
return err
}
if opts.noInterpolate {
// we can't use ToProject, so the model we render here is only partially resolved
model, err := opts.ToModel(ctx, dockerCli, services)
if err != nil {
return err
}
content, err = backend.Config(ctx, project, api.ConfigOptions{
Format: opts.Format,
Output: opts.Output,
ResolveImageDigests: opts.resolveImageDigests,
})
if err != nil {
return err
if opts.resolveImageDigests {
err = resolveImageDigests(ctx, dockerCli, model)
if err != nil {
return err
}
}
content, err = formatModel(model, opts.Format)
if err != nil {
return err
}
} else {
project, err := opts.ToProject(ctx, dockerCli, services)
if err != nil {
return err
}
switch opts.Format {
case "json":
content, err = project.MarshalJSON()
case "yaml":
content, err = project.MarshalYAML()
default:
return fmt.Errorf("unsupported format %q", opts.Format)
}
if err != nil {
return err
}
}
if !opts.noInterpolate {
@@ -150,19 +193,69 @@ func runConfig(ctx context.Context, dockerCli command.Cli, backend api.Service,
if opts.Output != "" && len(content) > 0 {
return os.WriteFile(opts.Output, content, 0o666)
}
_, err = fmt.Fprint(dockerCli.Out(), string(content))
_, err := fmt.Fprint(dockerCli.Out(), string(content))
return err
}
func resolveImageDigests(ctx context.Context, dockerCli command.Cli, model map[string]any) (err error) {
// create a pseudo-project so we can rely on WithImagesResolved to resolve images
p := &types.Project{
Services: types.Services{},
}
services := model["services"].(map[string]any)
for name, s := range services {
service := s.(map[string]any)
if image, ok := service["image"]; ok {
p.Services[name] = types.ServiceConfig{
Image: image.(string),
}
}
}
p, err = p.WithImagesResolved(compose.ImageDigestResolver(ctx, dockerCli.ConfigFile(), dockerCli.Client()))
if err != nil {
return err
}
// Collect image resolved with digest and update model accordingly
for name, s := range services {
service := s.(map[string]any)
config := p.Services[name]
if config.Image != "" {
service["image"] = config.Image
}
services[name] = service
}
model["services"] = services
return nil
}
func formatModel(model map[string]any, format string) (content []byte, err error) {
switch format {
case "json":
content, err = json.MarshalIndent(model, "", " ")
case "yaml":
buf := bytes.NewBuffer([]byte{})
encoder := yaml.NewEncoder(buf)
encoder.SetIndent(2)
err = encoder.Encode(model)
content = buf.Bytes()
default:
return nil, fmt.Errorf("unsupported format %q", format)
}
return
}
func runServices(ctx context.Context, dockerCli command.Cli, opts configOptions) error {
project, err := opts.ToProject(ctx, dockerCli, nil, cli.WithoutEnvironmentResolution)
if err != nil {
return err
}
return project.WithServices(project.ServiceNames(), func(s types.ServiceConfig) error {
fmt.Fprintln(dockerCli.Out(), s.Name)
err = project.ForEachService(project.ServiceNames(), func(serviceName string, _ *types.ServiceConfig) error {
fmt.Fprintln(dockerCli.Out(), serviceName)
return nil
})
return err
}
func runVolumes(ctx context.Context, dockerCli command.Cli, opts configOptions) error {
@@ -210,7 +303,7 @@ func runHash(ctx context.Context, dockerCli command.Cli, opts configOptions) err
if err != nil {
return err
}
fmt.Fprintf(dockerCli.Out(), "%s %s\n", s.Name, hash)
fmt.Fprintf(dockerCli.Out(), "%s %s\n", name, hash)
}
return nil
}
@@ -248,6 +341,22 @@ func runConfigImages(ctx context.Context, dockerCli command.Cli, opts configOpti
return nil
}
func runVariables(ctx context.Context, dockerCli command.Cli, opts configOptions, services []string) error {
opts.noInterpolate = true
model, err := opts.ToModel(ctx, dockerCli, services, cli.WithoutEnvironmentResolution)
if err != nil {
return err
}
variables := template.ExtractVariables(model, template.DefaultPattern)
return formatter.Print(variables, "", dockerCli.Out(), func(w io.Writer) {
for name, variable := range variables {
_, _ = fmt.Fprintf(w, "%s\t%t\t%s\t%s\n", name, variable.Required, variable.DefaultValue, variable.PresenceValue)
}
}, "NAME", "REQUIRED", "DEFAULT VALUE", "ALTERNATE VALUE")
}
func escapeDollarSign(marshal []byte) []byte {
dollar := []byte{'$'}
escDollar := []byte{'$', '$'}

View File

@@ -65,10 +65,10 @@ func copyCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
flags := copyCmd.Flags()
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.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.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)")
@@ -76,7 +76,7 @@ func copyCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runCopy(ctx context.Context, dockerCli command.Cli, backend api.Service, opts copyOptions) error {
name, err := opts.toProjectName(dockerCli)
name, err := opts.toProjectName(ctx, dockerCli)
if err != nil {
return err
}

View File

@@ -24,7 +24,7 @@ import (
"strings"
"time"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
@@ -55,7 +55,7 @@ func createCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service
}
cmd := &cobra.Command{
Use: "create [OPTIONS] [SERVICE...]",
Short: "Creates containers for a service.",
Short: "Creates containers for a service",
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
opts.pullChanged = cmd.Flags().Changed("pull")
if opts.Build && opts.noBuild {
@@ -72,12 +72,13 @@ func createCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
flags := cmd.Flags()
flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers.")
flags.BoolVar(&opts.noBuild, "no-build", false, "Don't build an image, even if it's policy.")
flags.BoolVar(&opts.Build, "build", false, "Build images before starting containers")
flags.BoolVar(&opts.noBuild, "no-build", false, "Don't build an image, even if it's policy")
flags.StringVar(&opts.Pull, "pull", "policy", `Pull image before running ("always"|"missing"|"never"|"build")`)
flags.BoolVar(&opts.forceRecreate, "force-recreate", false, "Recreate containers even if their configuration and image haven't changed.")
flags.BoolVar(&opts.quietPull, "quiet-pull", false, "Pull without printing progress information")
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.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
}
@@ -105,7 +106,7 @@ func runCreate(ctx context.Context, _ command.Cli, backend api.Service, createOp
RecreateDependencies: createOpts.dependenciesRecreateStrategy(),
Inherit: !createOpts.noInherit,
Timeout: createOpts.GetTimeout(),
QuietPull: false,
QuietPull: createOpts.quietPull,
})
}
@@ -159,22 +160,20 @@ func (opts createOptions) Apply(project *types.Project) error {
project.Services[i] = service
}
}
// opts.noBuild, however, means do not perform ANY builds
if opts.noBuild {
for i, service := range project.Services {
service.Build = nil
if service.Image == "" {
service.Image = api.GetImageNameOrDefault(service, project.Name)
}
project.Services[i] = service
}
}
if err := applyPlatforms(project, true); err != nil {
return err
}
for _, scale := range opts.scale {
err := applyScaleOpts(project, opts.scale)
if err != nil {
return err
}
return nil
}
func applyScaleOpts(project *types.Project, opts []string) error {
for _, scale := range opts {
split := strings.Split(scale, "=")
if len(split) != 2 {
return fmt.Errorf("invalid --scale option %q. Should be SERVICE=NUM", scale)
@@ -184,7 +183,7 @@ func (opts createOptions) Apply(project *types.Project) error {
if err != nil {
return err
}
err = setServiceScale(project, name, uint64(replicas))
err = setServiceScale(project, name, replicas)
if err != nil {
return err
}

View File

@@ -21,13 +21,13 @@ import (
"fmt"
"testing"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/davecgh/go-spew/spew"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/mocks"
"github.com/golang/mock/gomock"
"github.com/google/go-cmp/cmp"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
)
func TestRunCreate(t *testing.T) {
@@ -86,7 +86,7 @@ func sampleProject() *types.Project {
return &types.Project{
Name: "test",
Services: types.Services{
{
"svc": {
Name: "svc",
Build: &types.BuildConfig{
Context: ".",

View File

@@ -63,9 +63,9 @@ func downCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
flags := downCmd.Flags()
removeOrphans := utils.StringToBool(os.Getenv(ComposeRemoveOrphans))
flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.")
flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file")
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.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" {
@@ -78,7 +78,7 @@ func downCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runDown(ctx context.Context, dockerCli command.Cli, backend api.Service, opts downOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}

View File

@@ -40,7 +40,7 @@ func eventsCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service
}
cmd := &cobra.Command{
Use: "events [OPTIONS] [SERVICE...]",
Short: "Receive real time events from containers.",
Short: "Receive real time events from containers",
RunE: Adapt(func(ctx context.Context, args []string) error {
return runEvents(ctx, dockerCli, backend, opts, args)
}),
@@ -52,7 +52,7 @@ func eventsCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service
}
func runEvents(ctx context.Context, dockerCli command.Cli, backend api.Service, opts eventsOpts, services []string) error {
name, err := opts.toProjectName(dockerCli)
name, err := opts.toProjectName(ctx, dockerCli)
if err != nil {
return err
}

View File

@@ -19,7 +19,7 @@ package compose
import (
"context"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/pkg/api"
@@ -51,7 +51,7 @@ func execCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
runCmd := &cobra.Command{
Use: "exec [OPTIONS] SERVICE COMMAND [ARGS...]",
Short: "Execute a command in a running container.",
Short: "Execute a command in a running container",
Args: cobra.MinimumNArgs(2),
PreRunE: Adapt(func(ctx context.Context, args []string) error {
opts.service = args[0]
@@ -64,17 +64,17 @@ func execCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
runCmd.Flags().BoolVarP(&opts.detach, "detach", "d", false, "Detached mode: Run command in the background.")
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", 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().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().StringVarP(&opts.workingDir, "workdir", "w", "", "Path to workdir directory for this command.")
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.")
runCmd.Flags().BoolVarP(&opts.interactive, "interactive", "i", true, "Keep STDIN open even if not attached")
runCmd.Flags().MarkHidden("interactive") //nolint:errcheck
runCmd.Flags().BoolP("tty", "t", true, "Allocate a pseudo-TTY.")
runCmd.Flags().BoolP("tty", "t", true, "Allocate a pseudo-TTY")
runCmd.Flags().MarkHidden("tty") //nolint:errcheck
runCmd.Flags().SetInterspersed(false)
@@ -82,7 +82,7 @@ func execCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runExec(ctx context.Context, dockerCli command.Cli, backend api.Service, opts execOpts) error {
projectName, err := opts.toProjectName(dockerCli)
projectName, err := opts.toProjectName(ctx, dockerCli)
if err != nil {
return err
}

View File

@@ -51,13 +51,13 @@ func imagesCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service
}),
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
imgCmd.Flags().StringVar(&opts.Format, "format", "table", "Format the output. Values: [table | json].")
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, dockerCli command.Cli, backend api.Service, opts imageOptions, services []string) error {
projectName, err := opts.toProjectName(dockerCli)
projectName, err := opts.toProjectName(ctx, dockerCli)
if err != nil {
return err
}

View File

@@ -39,7 +39,7 @@ func killCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
cmd := &cobra.Command{
Use: "kill [OPTIONS] [SERVICE...]",
Short: "Force stop service containers.",
Short: "Force stop service containers",
RunE: Adapt(func(ctx context.Context, args []string) error {
return runKill(ctx, dockerCli, backend, opts, args)
}),
@@ -48,14 +48,14 @@ func killCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
flags := cmd.Flags()
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.")
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")
return cmd
}
func runKill(ctx context.Context, dockerCli command.Cli, backend api.Service, opts killOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}

View File

@@ -49,9 +49,9 @@ func listCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
Args: cobra.NoArgs,
ValidArgsFunction: noCompletion(),
}
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().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")
return lsCmd

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"errors"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
@@ -30,6 +31,7 @@ type logsOptions struct {
*ProjectOptions
composeOptions
follow bool
index int
tail string
since string
until string
@@ -48,29 +50,47 @@ func logsCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
RunE: Adapt(func(ctx context.Context, args []string) error {
return runLogs(ctx, dockerCli, backend, opts, args)
}),
PreRunE: func(cmd *cobra.Command, args []string) error {
if opts.index > 0 && len(args) != 1 {
return errors.New("--index requires one service to be selected")
}
return nil
},
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
flags := logsCmd.Flags()
flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output.")
flags.BoolVarP(&opts.follow, "follow", "f", false, "Follow log output")
flags.IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas")
flags.StringVar(&opts.since, "since", "", "Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)")
flags.StringVar(&opts.until, "until", "", "Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)")
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.StringVarP(&opts.tail, "tail", "n", "all", "Number of lines to show from the end of the logs for each container.")
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.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, dockerCli command.Cli, backend api.Service, opts logsOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}
// exclude services configured to ignore output (attach: false), until explicitly selected
if project != nil && len(services) == 0 {
for n, service := range project.Services {
if service.Attach == nil || *service.Attach {
services = append(services, n)
}
}
}
consumer := formatter.NewLogConsumer(ctx, dockerCli.Out(), dockerCli.Err(), !opts.noColor, !opts.noPrefix, false)
return backend.Logs(ctx, name, consumer, api.LogOptions{
Project: project,
Services: services,
Follow: opts.follow,
Index: opts.index,
Tail: opts.tail,
Since: opts.since,
Until: opts.until,

View File

@@ -19,16 +19,13 @@ package compose
import (
"fmt"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/compose/v2/pkg/utils"
)
func applyPlatforms(project *types.Project, buildForSinglePlatform bool) error {
defaultPlatform := project.Environment["DOCKER_DEFAULT_PLATFORM"]
for i := range project.Services {
// mutable reference so platform fields can be updated
service := &project.Services[i]
for name, service := range project.Services {
if service.Build == nil {
continue
}
@@ -36,7 +33,7 @@ func applyPlatforms(project *types.Project, buildForSinglePlatform bool) error {
// default platform only applies if the service doesn't specify
if defaultPlatform != "" && service.Platform == "" {
if len(service.Build.Platforms) > 0 && !utils.StringContains(service.Build.Platforms, defaultPlatform) {
return fmt.Errorf("service %q build.platforms does not support value set by DOCKER_DEFAULT_PLATFORM: %s", service.Name, defaultPlatform)
return fmt.Errorf("service %q build.platforms does not support value set by DOCKER_DEFAULT_PLATFORM: %s", name, defaultPlatform)
}
service.Platform = defaultPlatform
}
@@ -44,7 +41,7 @@ func applyPlatforms(project *types.Project, buildForSinglePlatform bool) error {
if service.Platform != "" {
if len(service.Build.Platforms) > 0 {
if !utils.StringContains(service.Build.Platforms, service.Platform) {
return fmt.Errorf("service %q build configuration does not support platform: %s", service.Name, service.Platform)
return fmt.Errorf("service %q build configuration does not support platform: %s", name, service.Platform)
}
}
@@ -71,6 +68,7 @@ func applyPlatforms(project *types.Project, buildForSinglePlatform bool) error {
// empty indicates that the builder gets to decide
service.Build.Platforms = nil
}
project.Services[name] = service
}
return nil
}

View File

@@ -19,7 +19,7 @@ package compose
import (
"testing"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/stretchr/testify/require"
)
@@ -27,7 +27,7 @@ func TestApplyPlatforms_InferFromRuntime(t *testing.T) {
makeProject := func() *types.Project {
return &types.Project{
Services: types.Services{
{
"test": {
Name: "test",
Image: "foo",
Build: &types.BuildConfig{
@@ -47,14 +47,14 @@ func TestApplyPlatforms_InferFromRuntime(t *testing.T) {
t.Run("SinglePlatform", func(t *testing.T) {
project := makeProject()
require.NoError(t, applyPlatforms(project, true))
require.EqualValues(t, []string{"alice/32"}, project.Services[0].Build.Platforms)
require.EqualValues(t, []string{"alice/32"}, project.Services["test"].Build.Platforms)
})
t.Run("MultiPlatform", func(t *testing.T) {
project := makeProject()
require.NoError(t, applyPlatforms(project, false))
require.EqualValues(t, []string{"linux/amd64", "linux/arm64", "alice/32"},
project.Services[0].Build.Platforms)
project.Services["test"].Build.Platforms)
})
}
@@ -65,7 +65,7 @@ func TestApplyPlatforms_DockerDefaultPlatform(t *testing.T) {
"DOCKER_DEFAULT_PLATFORM": "linux/amd64",
},
Services: types.Services{
{
"test": {
Name: "test",
Image: "foo",
Build: &types.BuildConfig{
@@ -83,14 +83,14 @@ func TestApplyPlatforms_DockerDefaultPlatform(t *testing.T) {
t.Run("SinglePlatform", func(t *testing.T) {
project := makeProject()
require.NoError(t, applyPlatforms(project, true))
require.EqualValues(t, []string{"linux/amd64"}, project.Services[0].Build.Platforms)
require.EqualValues(t, []string{"linux/amd64"}, project.Services["test"].Build.Platforms)
})
t.Run("MultiPlatform", func(t *testing.T) {
project := makeProject()
require.NoError(t, applyPlatforms(project, false))
require.EqualValues(t, []string{"linux/amd64", "linux/arm64"},
project.Services[0].Build.Platforms)
project.Services["test"].Build.Platforms)
})
}
@@ -101,7 +101,7 @@ func TestApplyPlatforms_UnsupportedPlatform(t *testing.T) {
"DOCKER_DEFAULT_PLATFORM": "commodore/64",
},
Services: types.Services{
{
"test": {
Name: "test",
Image: "foo",
Build: &types.BuildConfig{

View File

@@ -45,7 +45,7 @@ func pauseCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runPause(ctx context.Context, dockerCli command.Cli, backend api.Service, opts pauseOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}
@@ -76,7 +76,7 @@ func unpauseCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Servic
}
func runUnPause(ctx context.Context, dockerCli command.Cli, backend api.Service, opts unpauseOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}

View File

@@ -41,7 +41,7 @@ func portCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
cmd := &cobra.Command{
Use: "port [OPTIONS] SERVICE PRIVATE_PORT",
Short: "Print the public port for a port binding.",
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.ParseUint(args[1], 10, 16)
@@ -58,12 +58,12 @@ func portCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
cmd.Flags().StringVar(&opts.protocol, "protocol", "tcp", "tcp or udp")
cmd.Flags().IntVar(&opts.index, "index", 0, "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, dockerCli command.Cli, backend api.Service, opts portOptions, service string) error {
projectName, err := opts.toProjectName(dockerCli)
projectName, err := opts.toProjectName(ctx, dockerCli)
if err != nil {
return err
}

View File

@@ -42,6 +42,7 @@ type psOptions struct {
Filter string
Status []string
noTrunc bool
Orphans bool
}
func (p *psOptions) parseFilter() error {
@@ -80,33 +81,39 @@ func psCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *c
}
flags := psCmd.Flags()
flags.StringVar(&opts.Format, "format", "table", cliflags.FormatHelp)
flags.StringVar(&opts.Filter, "filter", "", "Filter services by a property (supported filters: status).")
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")
flags.BoolVar(&opts.Services, "services", false, "Display services")
flags.BoolVar(&opts.Orphans, "orphans", true, "Include orphaned services (not declared by project)")
flags.BoolVarP(&opts.All, "all", "a", false, "Show all stopped containers (including those created by the run command)")
flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Don't truncate output")
return psCmd
}
func runPs(ctx context.Context, dockerCli command.Cli, backend api.Service, services []string, opts psOptions) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}
if project != nil && len(services) > 0 {
if project != nil {
names := project.ServiceNames()
for _, service := range services {
if !utils.StringContains(names, service) {
return fmt.Errorf("no such service: %s", service)
if len(services) > 0 {
for _, service := range services {
if !utils.StringContains(names, service) {
return fmt.Errorf("no such service: %s", service)
}
}
} else if !opts.Orphans {
// until user asks to list orphaned services, we only include those declared in project
services = names
}
}
containers, err := backend.Ps(ctx, name, api.PsOptions{
Project: project,
All: opts.All,
All: opts.All || len(opts.Status) != 0,
Services: services,
})
if err != nil {

View File

@@ -26,8 +26,8 @@ import (
"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"
"go.uber.org/mock/gomock"
)
func TestPsTable(t *testing.T) {

View File

@@ -28,6 +28,7 @@ import (
type publishOptions struct {
*ProjectOptions
resolveImageDigests bool
ociVersion string
}
func publishCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
@@ -43,17 +44,19 @@ func publishCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Servic
Args: cobra.ExactArgs(1),
}
flags := cmd.Flags()
flags.BoolVar(&opts.resolveImageDigests, "resolve-image-digests", false, "Pin image tags to digests.")
flags.BoolVar(&opts.resolveImageDigests, "resolve-image-digests", false, "Pin image tags to digests")
flags.StringVar(&opts.ociVersion, "oci-version", "", "OCI Image/Artifact specification version (automatically determined by default)")
return cmd
}
func runPublish(ctx context.Context, dockerCli command.Cli, backend api.Service, opts publishOptions, repository string) error {
project, err := opts.ToProject(dockerCli, nil)
project, _, err := opts.ToProject(ctx, dockerCli, nil)
if err != nil {
return err
}
return backend.Publish(ctx, project, repository, api.PublishOptions{
ResolveImageDigests: opts.resolveImageDigests,
OCIVersion: api.OCIVersion(opts.ociVersion),
})
}

View File

@@ -21,7 +21,7 @@ import (
"fmt"
"os"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
"github.com/morikuni/aec"
"github.com/spf13/cobra"
@@ -60,23 +60,24 @@ func pullCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
ValidArgsFunction: completeServiceNames(dockerCli, 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.")
cmd.Flags().BoolVar(&opts.parallel, "parallel", true, "DEPRECATED pull multiple images in parallel.")
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.")
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.noBuildable, "ignore-buildable", false, "Ignore images that can be built.")
cmd.Flags().StringVar(&opts.policy, "policy", "", `Apply pull policy ("missing"|"always").`)
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")
cmd.Flags().StringVar(&opts.policy, "policy", "", `Apply pull policy ("missing"|"always")`)
return cmd
}
func (opts pullOptions) apply(project *types.Project, services []string) error {
func (opts pullOptions) apply(project *types.Project, services []string) (*types.Project, error) {
if !opts.includeDeps {
err := project.ForServices(services, types.IgnoreDependencies)
var err error
project, err = project.WithSelectedServices(services, types.IgnoreDependencies)
if err != nil {
return err
return nil, err
}
}
@@ -89,16 +90,16 @@ func (opts pullOptions) apply(project *types.Project, services []string) error {
project.Services[i] = service
}
}
return nil
return project, nil
}
func runPull(ctx context.Context, dockerCli command.Cli, backend api.Service, opts pullOptions, services []string) error {
project, err := opts.ToProject(dockerCli, services)
project, _, err := opts.ToProject(ctx, dockerCli, services)
if err != nil {
return err
}
err = opts.apply(project, services)
project, err = opts.apply(project, services)
if err != nil {
return err
}

View File

@@ -19,39 +19,39 @@ package compose
import (
"testing"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"gotest.tools/v3/assert"
)
func TestApplyPullOptions(t *testing.T) {
project := &types.Project{
Services: types.Services{
{
"must-build": {
Name: "must-build",
// No image, local build only
Build: &types.BuildConfig{
Context: ".",
},
},
{
"has-build": {
Name: "has-build",
Image: "registry.example.com/myservice",
Build: &types.BuildConfig{
Context: ".",
},
},
{
"must-pull": {
Name: "must-pull",
Image: "registry.example.com/another-service",
},
},
}
err := pullOptions{
project, err := pullOptions{
policy: types.PullPolicyMissing,
}.apply(project, nil)
assert.NilError(t, err)
assert.Equal(t, project.Services[0].PullPolicy, "") // still default
assert.Equal(t, project.Services[1].PullPolicy, types.PullPolicyMissing)
assert.Equal(t, project.Services[2].PullPolicy, types.PullPolicyMissing)
assert.Equal(t, project.Services["must-build"].PullPolicy, "") // still default
assert.Equal(t, project.Services["has-build"].PullPolicy, types.PullPolicyMissing)
assert.Equal(t, project.Services["must-pull"].PullPolicy, types.PullPolicyMissing)
}

View File

@@ -19,7 +19,7 @@ package compose
import (
"context"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
"github.com/spf13/cobra"
@@ -54,13 +54,13 @@ func pushCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runPush(ctx context.Context, dockerCli command.Cli, backend api.Service, opts pushOptions, services []string) error {
project, err := opts.ToProject(dockerCli, services)
project, _, err := opts.ToProject(ctx, dockerCli, services)
if err != nil {
return err
}
if !opts.IncludeDeps {
err := project.ForServices(services, types.IgnoreDependencies)
project, err = project.WithSelectedServices(services, types.IgnoreDependencies)
if err != nil {
return err
}

View File

@@ -60,7 +60,7 @@ Any data which is not in a volume will be lost.`,
}
func runRemove(ctx context.Context, dockerCli command.Cli, backend api.Service, opts removeOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}

View File

@@ -50,19 +50,19 @@ func restartCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Servic
}
flags := restartCmd.Flags()
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.")
flags.BoolVar(&opts.noDeps, "no-deps", false, "Don't restart dependent services")
return restartCmd
}
func runRestart(ctx context.Context, dockerCli command.Cli, backend api.Service, opts restartOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli)
project, name, err := opts.projectOrName(ctx, dockerCli)
if err != nil {
return err
}
if project != nil && len(services) > 0 {
err := project.EnableServices(services...)
project, err = project.WithServicesEnabled(services...)
if err != nil {
return err
}

View File

@@ -21,11 +21,12 @@ import (
"fmt"
"strings"
xprogress "github.com/docker/buildx/util/progress"
"github.com/compose-spec/compose-go/v2/format"
xprogress "github.com/moby/buildkit/util/progress/progressui"
"github.com/sirupsen/logrus"
cgo "github.com/compose-spec/compose-go/cli"
"github.com/compose-spec/compose-go/loader"
"github.com/compose-spec/compose-go/types"
cgo "github.com/compose-spec/compose-go/v2/cli"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/opts"
"github.com/mattn/go-shellwords"
@@ -65,17 +66,18 @@ type runOptions struct {
quietPull bool
}
func (options runOptions) apply(project *types.Project) error {
func (options runOptions) apply(project *types.Project) (*types.Project, error) {
if options.noDeps {
err := project.ForServices([]string{options.Service}, types.IgnoreDependencies)
var err error
project, err = project.WithSelectedServices([]string{options.Service}, types.IgnoreDependencies)
if err != nil {
return err
return nil, err
}
}
target, err := project.GetService(options.Service)
if err != nil {
return err
return nil, err
}
target.Tty = !options.noTty
@@ -83,31 +85,34 @@ func (options runOptions) apply(project *types.Project) error {
// --service-ports and --publish are incompatible
if !options.servicePorts {
if len(target.Ports) > 0 {
logrus.Debug("Running service without ports exposed as --service-ports=false")
}
target.Ports = []types.ServicePortConfig{}
for _, p := range options.publish {
config, err := types.ParsePortConfig(p)
if err != nil {
return err
return nil, err
}
target.Ports = append(target.Ports, config...)
}
}
for _, v := range options.volumes {
volume, err := loader.ParseVolume(v)
volume, err := format.ParseVolume(v)
if err != nil {
return err
return nil, err
}
target.Volumes = append(target.Volumes, volume)
}
for i, s := range project.Services {
if s.Name == options.Service {
project.Services[i] = target
for name := range project.Services {
if name == options.Service {
project.Services[name] = target
break
}
}
return nil
return project, nil
}
func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
@@ -124,7 +129,7 @@ func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
}
cmd := &cobra.Command{
Use: "run [OPTIONS] SERVICE [COMMAND] [ARGS...]",
Short: "Run a one-off command on a 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 {
options.Service = args[0]
@@ -151,13 +156,13 @@ func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
return nil
}),
RunE: Adapt(func(ctx context.Context, args []string) error {
project, err := p.ToProject(dockerCli, []string{options.Service}, cgo.WithResolvedPaths(true), cgo.WithDiscardEnvFile)
project, _, err := p.ToProject(ctx, dockerCli, []string{options.Service}, cgo.WithResolvedPaths(true), cgo.WithDiscardEnvFile)
if err != nil {
return err
}
if createOpts.quietPull {
buildOpts.Progress = xprogress.PrinterModeQuiet
buildOpts.Progress = string(xprogress.QuietMode)
}
options.ignoreOrphans = utils.StringToBool(project.Environment[ComposeIgnoreOrphans])
@@ -170,24 +175,24 @@ func runCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
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", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected).")
flags.BoolVarP(&options.noTty, "no-TTY", "T", !dockerCli.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.")
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.BoolVarP(&options.servicePorts, "service-ports", "P", false, "Run command with all 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(&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().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)
@@ -206,7 +211,7 @@ func normalizeRunFlags(f *pflag.FlagSet, name string) pflag.NormalizedName {
}
func runRun(ctx context.Context, backend api.Service, project *types.Project, options runOptions, createOpts createOptions, buildOpts buildOptions, dockerCli command.Cli) error {
err := options.apply(project)
project, err := options.apply(project)
if err != nil {
return err
}
@@ -226,7 +231,7 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
}
buildForDeps = &bo
}
return startDependencies(ctx, backend, *project, buildForDeps, options.Service, options.ignoreOrphans)
return startDependencies(ctx, backend, *project, buildForDeps, options)
}, dockerCli.Err())
if err != nil {
return err
@@ -275,10 +280,10 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
QuietPull: options.quietPull,
}
for i, service := range project.Services {
if service.Name == options.Service {
for name, service := range project.Services {
if name == options.Service {
service.StdinOpen = options.interactive
project.Services[i] = service
project.Services[name] = service
}
}
@@ -293,22 +298,23 @@ func runRun(ctx context.Context, backend api.Service, project *types.Project, op
return err
}
func startDependencies(ctx context.Context, backend api.Service, project types.Project, buildOpts *api.BuildOptions, requestedServiceName string, ignoreOrphans bool) error {
func startDependencies(ctx context.Context, backend api.Service, project types.Project, buildOpts *api.BuildOptions, options runOptions) error {
dependencies := types.Services{}
var requestedService types.ServiceConfig
for _, service := range project.Services {
if service.Name != requestedServiceName {
dependencies = append(dependencies, service)
for name, service := range project.Services {
if name != options.Service {
dependencies[name] = service
} else {
requestedService = service
}
}
project.Services = dependencies
project.DisabledServices = append(project.DisabledServices, requestedService)
project.DisabledServices[options.Service] = requestedService
err := backend.Create(ctx, &project, api.CreateOptions{
Build: buildOpts,
IgnoreOrphans: ignoreOrphans,
IgnoreOrphans: options.ignoreOrphans,
QuietPull: options.quietPull,
})
if err != nil {
return err

View File

@@ -24,7 +24,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"golang.org/x/exp/maps"
"github.com/docker/compose/v2/pkg/api"
@@ -54,37 +54,31 @@ func scaleCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
flags := scaleCmd.Flags()
flags.BoolVar(&opts.noDeps, "no-deps", false, "Don't start linked services.")
flags.BoolVar(&opts.noDeps, "no-deps", false, "Don't start linked services")
return scaleCmd
}
func runScale(ctx context.Context, dockerCli command.Cli, backend api.Service, opts scaleOptions, serviceReplicaTuples map[string]int) error {
services := maps.Keys(serviceReplicaTuples)
project, err := opts.ToProject(dockerCli, services)
project, _, err := opts.ToProject(ctx, dockerCli, services)
if err != nil {
return err
}
if opts.noDeps {
if err := project.ForServices(services, types.IgnoreDependencies); err != nil {
if project, err = project.WithSelectedServices(services, types.IgnoreDependencies); err != nil {
return err
}
}
for key, value := range serviceReplicaTuples {
for i, service := range project.Services {
if service.Name != key {
continue
}
if service.Deploy == nil {
service.Deploy = &types.DeployConfig{}
}
scale := uint64(value)
service.Deploy.Replicas = &scale
project.Services[i] = service
break
service, err := project.GetService(key)
if err != nil {
return err
}
service.SetScale(value)
project.Services[key] = service
}
return backend.Scale(ctx, project, api.ScaleOptions{Services: services})

View File

@@ -44,7 +44,7 @@ func startCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runStart(ctx context.Context, dockerCli command.Cli, backend api.Service, opts startOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}

84
cmd/compose/stats.go Normal file
View File

@@ -0,0 +1,84 @@
/*
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"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/container"
"github.com/docker/docker/api/types/filters"
"github.com/spf13/cobra"
"github.com/docker/compose/v2/pkg/api"
)
type statsOptions struct {
ProjectOptions *ProjectOptions
all bool
format string
noStream bool
noTrunc bool
}
func statsCommand(p *ProjectOptions, dockerCli command.Cli) *cobra.Command {
opts := statsOptions{
ProjectOptions: p,
}
cmd := &cobra.Command{
Use: "stats [OPTIONS] [SERVICE]",
Short: "Display a live stream of container(s) resource usage statistics",
Args: cobra.MaximumNArgs(1),
RunE: Adapt(func(ctx context.Context, args []string) error {
return runStats(ctx, dockerCli, opts, args)
}),
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
flags := cmd.Flags()
flags.BoolVarP(&opts.all, "all", "a", false, "Show all containers (default shows just running)")
flags.StringVar(&opts.format, "format", "", `Format output using a custom template:
'table': Print output in table format with column headers (default)
'table TEMPLATE': Print output in table format using the given Go template
'json': Print in JSON format
'TEMPLATE': Print output using the given Go template.
Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates`)
flags.BoolVar(&opts.noStream, "no-stream", false, "Disable streaming stats and only pull the first result")
flags.BoolVar(&opts.noTrunc, "no-trunc", false, "Do not truncate output")
return cmd
}
func runStats(ctx context.Context, dockerCli command.Cli, opts statsOptions, service []string) error {
name, err := opts.ProjectOptions.toProjectName(ctx, dockerCli)
if err != nil {
return err
}
filter := []filters.KeyValuePair{
filters.Arg("label", fmt.Sprintf("%s=%s", api.ProjectLabel, name)),
}
if len(service) > 0 {
filter = append(filter, filters.Arg("label", fmt.Sprintf("%s=%s", api.ServiceLabel, service[0])))
}
args := filters.NewArgs(filter...)
return container.RunStats(ctx, dockerCli, &container.StatsOptions{
All: opts.all,
NoStream: opts.noStream,
NoTrunc: opts.noTrunc,
Format: opts.format,
Filters: &args,
})
}

View File

@@ -54,7 +54,7 @@ func stopCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runStop(ctx context.Context, dockerCli command.Cli, backend api.Service, opts stopOptions, services []string) error {
project, name, err := opts.projectOrName(dockerCli, services...)
project, name, err := opts.projectOrName(ctx, dockerCli, services...)
if err != nil {
return err
}

View File

@@ -50,7 +50,7 @@ func topCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
}
func runTop(ctx context.Context, dockerCli command.Cli, backend api.Service, opts topOptions, services []string) error {
projectName, err := opts.toProjectName(dockerCli)
projectName, err := opts.toProjectName(ctx, dockerCli)
if err != nil {
return err
}

View File

@@ -20,14 +20,15 @@ import (
"context"
"errors"
"fmt"
"os"
"strings"
"time"
xprogress "github.com/docker/buildx/util/progress"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/compose/v2/internal/experimental"
xprogress "github.com/moby/buildkit/util/progress/progressui"
"github.com/spf13/cobra"
"github.com/docker/compose/v2/pkg/api"
@@ -41,40 +42,44 @@ type composeOptions struct {
type upOptions struct {
*composeOptions
Detach bool
noStart bool
noDeps bool
cascadeStop bool
exitCodeFrom string
noColor bool
noPrefix bool
attachDependencies bool
attach []string
noAttach []string
timestamp bool
wait bool
waitTimeout int
Detach bool
noStart bool
noDeps bool
cascadeStop bool
exitCodeFrom string
noColor bool
noPrefix bool
attachDependencies bool
attach []string
noAttach []string
timestamp bool
wait bool
waitTimeout int
watch bool
navigationMenu bool
navigationMenuChanged bool
}
func (opts upOptions) apply(project *types.Project, services []string) error {
func (opts upOptions) apply(project *types.Project, services []string) (*types.Project, error) {
if opts.noDeps {
err := project.ForServices(services, types.IgnoreDependencies)
var err error
project, err = project.WithSelectedServices(services, types.IgnoreDependencies)
if err != nil {
return err
return nil, err
}
}
if opts.exitCodeFrom != "" {
_, err := project.GetService(opts.exitCodeFrom)
if err != nil {
return err
return nil, err
}
}
return nil
return project, nil
}
func upCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
func upCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service, experiments *experimental.State) *cobra.Command {
up := upOptions{}
create := createOptions{}
build := buildOptions{ProjectOptions: p}
@@ -84,6 +89,7 @@ func upCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *c
PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
create.pullChanged = cmd.Flags().Changed("pull")
create.timeChanged = cmd.Flags().Changed("timeout")
up.navigationMenuChanged = cmd.Flags().Changed("menu")
return validateFlags(&up, &create)
}),
RunE: p.WithServices(dockerCli, func(ctx context.Context, project *types.Project, services []string) error {
@@ -94,35 +100,39 @@ func upCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *c
if len(up.attach) != 0 && up.attachDependencies {
return errors.New("cannot combine --attach and --attach-dependencies")
}
return runUp(ctx, dockerCli, backend, create, up, build, project, services)
return runUp(ctx, dockerCli, backend, experiments, create, up, build, project, services)
}),
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
flags := upCmd.Flags()
flags.BoolVarP(&up.Detach, "detach", "d", false, "Detached mode: Run containers in the background")
flags.BoolVar(&create.Build, "build", false, "Build images before starting containers.")
flags.BoolVar(&create.noBuild, "no-build", false, "Don't build an image, even if it's policy.")
flags.BoolVar(&create.Build, "build", false, "Build images before starting containers")
flags.BoolVar(&create.noBuild, "no-build", false, "Don't build an image, even if it's policy")
flags.StringVar(&create.Pull, "pull", "policy", `Pull image before running ("always"|"missing"|"never")`)
flags.BoolVar(&create.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
removeOrphans := utils.StringToBool(os.Getenv(ComposeRemoveOrphans))
flags.BoolVar(&create.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file")
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.")
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")
flags.BoolVar(&create.noRecreate, "no-recreate", false, "If containers already exist, don't recreate them. Incompatible with --force-recreate.")
flags.BoolVar(&up.noStart, "no-start", false, "Don't start the services after creating them.")
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", 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.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(&create.quietPull, "quiet-pull", false, "Pull without printing progress information.")
flags.BoolVarP(&create.noInherit, "renew-anon-volumes", "V", false, "Recreate anonymous volumes instead of retrieving data from the previous containers")
flags.BoolVar(&create.quietPull, "quiet-pull", false, "Pull without printing progress information")
flags.StringArrayVar(&up.attach, "attach", []string{}, "Restrict attaching to the specified services. Incompatible with --attach-dependencies.")
flags.StringArrayVar(&up.noAttach, "no-attach", []string{}, "Do not attach (stream logs) to the specified services.")
flags.BoolVar(&up.attachDependencies, "attach-dependencies", false, "Automatically attach to log output of dependent services.")
flags.StringArrayVar(&up.noAttach, "no-attach", []string{}, "Do not attach (stream logs) to the specified services")
flags.BoolVar(&up.attachDependencies, "attach-dependencies", false, "Automatically attach to log output of dependent services")
flags.BoolVar(&up.wait, "wait", false, "Wait for services to be running|healthy. Implies detached mode.")
flags.IntVar(&up.waitTimeout, "wait-timeout", 0, "Maximum duration to wait for the project to be running|healthy.")
flags.IntVar(&up.waitTimeout, "wait-timeout", 0, "Maximum duration to wait for the project to be running|healthy")
flags.BoolVarP(&up.watch, "watch", "w", false, "Watch source code and rebuild/refresh containers when files are updated.")
flags.BoolVar(&up.navigationMenu, "menu", false, "Enable interactive shortcuts when running attached (Experimental). Incompatible with --detach.")
flags.MarkHidden("menu") //nolint:errcheck
return upCmd
}
@@ -156,6 +166,7 @@ func runUp(
ctx context.Context,
dockerCli command.Cli,
backend api.Service,
experimentals *experimental.State,
createOptions createOptions,
upOptions upOptions,
buildOptions buildOptions,
@@ -171,17 +182,18 @@ func runUp(
return err
}
err = upOptions.apply(project, services)
project, err = upOptions.apply(project, services)
if err != nil {
return err
}
if !upOptions.navigationMenuChanged {
upOptions.navigationMenu = SetUnchangedOption(ComposeMenu, experimentals.NavBar())
}
var build *api.BuildOptions
// this check is technically redundant as createOptions::apply()
// already removed all the build sections
if !createOptions.noBuild {
if createOptions.quietPull {
buildOptions.Progress = xprogress.PrinterModeQuiet
buildOptions.Progress = string(xprogress.QuietMode)
}
// BuildOptions here is nested inside CreateOptions, so
// no service list is passed, it will implicitly pick all
@@ -231,9 +243,9 @@ func runUp(
if upOptions.attachDependencies {
dependencyOpt = types.IncludeDependencies
}
if err := project.WithServices(services, func(s types.ServiceConfig) error {
if err := project.ForEachService(services, func(serviceName string, s *types.ServiceConfig) error {
if s.Attach == nil || *s.Attach {
attachSet.Add(s.Name)
attachSet.Add(serviceName)
}
return nil
}, dependencyOpt); err != nil {
@@ -249,34 +261,26 @@ func runUp(
return backend.Up(ctx, project, api.UpOptions{
Create: create,
Start: api.StartOptions{
Project: project,
Attach: consumer,
AttachTo: attach,
ExitCodeFrom: upOptions.exitCodeFrom,
CascadeStop: upOptions.cascadeStop,
Wait: upOptions.wait,
WaitTimeout: timeout,
Services: services,
Project: project,
Attach: consumer,
AttachTo: attach,
ExitCodeFrom: upOptions.exitCodeFrom,
CascadeStop: upOptions.cascadeStop,
Wait: upOptions.wait,
WaitTimeout: timeout,
Watch: upOptions.watch,
Services: services,
NavigationMenu: upOptions.navigationMenu,
},
})
}
func setServiceScale(project *types.Project, name string, replicas uint64) error {
for i, s := range project.Services {
if s.Name != name {
continue
}
service, err := project.GetService(name)
if err != nil {
return err
}
if service.Deploy == nil {
service.Deploy = &types.DeployConfig{}
}
service.Deploy.Replicas = &replicas
project.Services[i] = service
return nil
func setServiceScale(project *types.Project, name string, replicas int) error {
service, err := project.GetService(name)
if err != nil {
return err
}
return fmt.Errorf("unknown service %q", name)
service.SetScale(replicas)
project.Services[name] = service
return nil
}

View File

@@ -19,25 +19,33 @@ package compose
import (
"testing"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"gotest.tools/v3/assert"
)
func TestApplyScaleOpt(t *testing.T) {
p := types.Project{
Services: types.Services{
{
"foo": {
Name: "foo",
},
{
"bar": {
Name: "bar",
Deploy: &types.DeployConfig{
Mode: "test",
},
},
},
}
opt := createOptions{scale: []string{"foo=2"}}
err := opt.Apply(&p)
err := applyScaleOpts(&p, []string{"foo=2", "bar=3"})
assert.NilError(t, err)
foo, err := p.GetService("foo")
assert.NilError(t, err)
assert.Equal(t, *foo.Deploy.Replicas, uint64(2))
assert.Equal(t, *foo.Scale, 2)
bar, err := p.GetService("bar")
assert.NilError(t, err)
assert.Equal(t, *bar.Scale, 3)
assert.Equal(t, *bar.Deploy.Replicas, 3)
}

View File

@@ -52,7 +52,7 @@ func versionCommand(dockerCli command.Cli) *cobra.Command {
// define flags for backward compatibility with com.docker.cli
flags := cmd.Flags()
flags.StringVarP(&opts.format, "format", "f", "", "Format the output. Values: [pretty | json]. (Default: pretty)")
flags.BoolVar(&opts.short, "short", false, "Shows only Compose's version number.")
flags.BoolVar(&opts.short, "short", false, "Shows only Compose's version number")
return cmd
}

View File

@@ -65,7 +65,7 @@ func vizCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *
func runViz(ctx context.Context, dockerCli command.Cli, backend api.Service, opts *vizOptions) error {
_, _ = fmt.Fprintln(os.Stderr, "viz command is EXPERIMENTAL")
project, err := opts.ToProject(dockerCli, nil)
project, _, err := opts.ToProject(ctx, dockerCli, nil)
if err != nil {
return err
}

View File

@@ -61,7 +61,7 @@ func waitCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
func runWait(ctx context.Context, dockerCli command.Cli, backend api.Service, opts *waitOptions) (int64, error) {
_, name, err := opts.projectOrName(dockerCli)
_, name, err := opts.projectOrName(ctx, dockerCli)
if err != nil {
return 0, err
}

View File

@@ -20,7 +20,8 @@ import (
"context"
"fmt"
"github.com/compose-spec/compose-go/types"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/internal/locker"
@@ -31,8 +32,7 @@ import (
type watchOptions struct {
*ProjectOptions
quiet bool
noUp bool
noUp bool
}
func watchCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
@@ -57,13 +57,13 @@ func watchCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
ValidArgsFunction: completeServiceNames(dockerCli, p),
}
cmd.Flags().BoolVar(&watchOpts.quiet, "quiet", false, "hide build output")
cmd.Flags().BoolVar(&buildOpts.quiet, "quiet", false, "hide build output")
cmd.Flags().BoolVar(&watchOpts.noUp, "no-up", false, "Do not build & start services before watching")
return cmd
}
func runWatch(ctx context.Context, dockerCli command.Cli, backend api.Service, watchOpts watchOptions, buildOpts buildOptions, services []string) error {
project, err := watchOpts.ToProject(dockerCli, nil)
project, _, err := watchOpts.ToProject(ctx, dockerCli, nil)
if err != nil {
return err
}
@@ -101,7 +101,7 @@ func runWatch(ctx context.Context, dockerCli command.Cli, backend api.Service, w
Recreate: api.RecreateDiverged,
RecreateDependencies: api.RecreateNever,
Inherit: true,
QuietPull: watchOpts.quiet,
QuietPull: buildOpts.quiet,
},
Start: api.StartOptions{
Project: project,
@@ -114,7 +114,10 @@ func runWatch(ctx context.Context, dockerCli command.Cli, backend api.Service, w
return err
}
}
consumer := formatter.NewLogConsumer(ctx, dockerCli.Out(), dockerCli.Err(), false, false, false)
return backend.Watch(ctx, project, services, api.WatchOptions{
Build: build,
Build: &build,
LogTo: consumer,
})
}

67
cmd/formatter/ansi.go Normal file
View File

@@ -0,0 +1,67 @@
/*
Copyright 2024 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 formatter
import (
"fmt"
"github.com/acarl005/stripansi"
)
func ansi(code string) string {
return fmt.Sprintf("\033%s", code)
}
func SaveCursor() {
fmt.Print(ansi("7"))
}
func RestoreCursor() {
fmt.Print(ansi("8"))
}
func HideCursor() {
fmt.Print(ansi("[?25l"))
}
func ShowCursor() {
fmt.Print(ansi("[?25h"))
}
func MoveCursor(y, x int) {
fmt.Print(ansi(fmt.Sprintf("[%d;%dH", y, x)))
}
func MoveCursorX(pos int) {
fmt.Print(ansi(fmt.Sprintf("[%dG", pos)))
}
func ClearLine() {
// Does not move cursor from its current position
fmt.Print(ansi("[2K"))
}
func MoveCursorUp(lines int) {
// Does not add new lines
fmt.Print(ansi(fmt.Sprintf("[%dA", lines)))
}
func MoveCursorDown(lines int) {
// Does not add new lines
fmt.Print(ansi(fmt.Sprintf("[%dB", lines)))
}
func NewLine() {
// Like \n
fmt.Print("\012")
}
func lenAnsi(s string) int {
// len has into consideration ansi codes, if we want
// the len of the actual len(string) we need to strip
// all ansi codes
return len(stripansi.Strip(s))
}

View File

@@ -35,6 +35,18 @@ var names = []string{
"white",
}
const (
BOLD = "1"
FAINT = "2"
ITALIC = "3"
UNDERLINE = "4"
)
const (
RESET = "0"
CYAN = "36"
)
const (
// Never use ANSI codes
Never = "never"
@@ -72,12 +84,17 @@ var monochrome = func(s string) string {
return s
}
func ansiColor(code, s string) string {
return fmt.Sprintf("%s%s%s", ansi(code), s, ansi("0"))
func ansiColor(code, s string, formatOpts ...string) string {
return fmt.Sprintf("%s%s%s", ansiColorCode(code, formatOpts...), s, ansiColorCode("0"))
}
func ansi(code string) string {
return fmt.Sprintf("\033[%sm", code)
// Everything about ansiColorCode color https://hyperskill.org/learn/step/18193
func ansiColorCode(code string, formatOpts ...string) string {
res := "\033["
for _, c := range formatOpts {
res = fmt.Sprintf("%s%s;", res, c)
}
return fmt.Sprintf("%s%sm", res, code)
}
func makeColorFunc(code string) colorFunc {

View File

@@ -33,6 +33,7 @@ const (
defaultContainerTableFormat = "table {{.Name}}\t{{.Image}}\t{{.Command}}\t{{.Service}}\t{{.RunningFor}}\t{{.Status}}\t{{.Ports}}"
nameHeader = "NAME"
projectHeader = "PROJECT"
serviceHeader = "SERVICE"
commandHeader = "COMMAND"
runningForHeader = "CREATED"
@@ -112,6 +113,7 @@ func NewContainerContext() *ContainerContext {
containerCtx.Header = formatter.SubHeaderContext{
"ID": formatter.ContainerIDHeader,
"Name": nameHeader,
"Project": projectHeader,
"Service": serviceHeader,
"Image": formatter.ImageHeader,
"Command": commandHeader,
@@ -164,6 +166,10 @@ func (c *ContainerContext) Service() string {
return c.c.Service
}
func (c *ContainerContext) Project() string {
return c.c.Project
}
func (c *ContainerContext) Image() string {
return c.c.Image
}

View File

@@ -62,7 +62,11 @@ func (l *logConsumer) Register(name string) {
func (l *logConsumer) register(name string) *presenter {
cf := monochrome
if l.color {
cf = nextColor()
if name == api.WatchLogger {
cf = makeColorFunc("92")
} else {
cf = nextColor()
}
}
p := &presenter{
colors: cf,
@@ -98,19 +102,29 @@ func (l *logConsumer) Err(container, message string) {
l.write(l.stderr, container, message)
}
var navColor = makeColorFunc("90")
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") {
if l.timestamp {
fmt.Fprintf(w, "%s%s%s\n", p.prefix, timestamp, line)
} else {
fmt.Fprintf(w, "%s%s\n", p.prefix, line)
printFn := func() {
p := l.getPresenter(container)
timestamp := time.Now().Format(jsonmessage.RFC3339NanoFixed)
for _, line := range strings.Split(message, "\n") {
ClearLine()
if l.timestamp {
fmt.Fprintf(w, "%s%s%s\n", p.prefix, timestamp, line)
} else {
fmt.Fprintf(w, "%s%s\n", p.prefix, line)
}
}
}
if KeyboardManager != nil {
KeyboardManager.PrintKeyboardInfo(printFn)
} else {
printFn()
}
}
func (l *logConsumer) Status(container, msg string) {
@@ -138,5 +152,9 @@ type presenter struct {
}
func (p *presenter) setPrefix(width int) {
if p.name == api.WatchLogger {
p.prefix = p.colors(strings.Repeat(" ", width) + " ⦿ ")
return
}
p.prefix = p.colors(fmt.Sprintf("%-"+strconv.Itoa(width)+"s | ", p.name))
}

321
cmd/formatter/shortcut.go Normal file
View File

@@ -0,0 +1,321 @@
/*
Copyright 2024 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 formatter
import (
"context"
"errors"
"fmt"
"math"
"os"
"syscall"
"time"
"github.com/buger/goterm"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/compose/v2/internal/tracing"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/watch"
"github.com/eiannone/keyboard"
"github.com/hashicorp/go-multierror"
"github.com/skratchdot/open-golang/open"
)
const DISPLAY_ERROR_TIME = 10
type KeyboardError struct {
err error
timeStart time.Time
}
func (ke *KeyboardError) shouldDisplay() bool {
return ke.err != nil && int(time.Since(ke.timeStart).Seconds()) < DISPLAY_ERROR_TIME
}
func (ke *KeyboardError) printError(height int, info string) {
if ke.shouldDisplay() {
errMessage := ke.err.Error()
MoveCursor(height-linesOffset(info)-linesOffset(errMessage)-1, 0)
ClearLine()
fmt.Print(errMessage)
}
}
func (ke *KeyboardError) addError(prefix string, err error) {
ke.timeStart = time.Now()
prefix = ansiColor(CYAN, fmt.Sprintf("%s →", prefix), BOLD)
errorString := fmt.Sprintf("%s %s", prefix, err.Error())
ke.err = errors.New(errorString)
}
func (ke *KeyboardError) error() string {
return ke.err.Error()
}
type KeyboardWatch struct {
Watcher watch.Notify
Watching bool
WatchFn func(ctx context.Context, project *types.Project, services []string, options api.WatchOptions) error
Ctx context.Context
Cancel context.CancelFunc
}
func (kw *KeyboardWatch) isWatching() bool {
return kw.Watching
}
func (kw *KeyboardWatch) switchWatching() {
kw.Watching = !kw.Watching
}
func (kw *KeyboardWatch) newContext(ctx context.Context) context.CancelFunc {
ctx, cancel := context.WithCancel(ctx)
kw.Ctx = ctx
kw.Cancel = cancel
return cancel
}
type KEYBOARD_LOG_LEVEL int
const (
NONE KEYBOARD_LOG_LEVEL = 0
INFO KEYBOARD_LOG_LEVEL = 1
DEBUG KEYBOARD_LOG_LEVEL = 2
)
type LogKeyboard struct {
kError KeyboardError
Watch KeyboardWatch
IsDockerDesktopActive bool
IsWatchConfigured bool
logLevel KEYBOARD_LOG_LEVEL
signalChannel chan<- os.Signal
}
var KeyboardManager *LogKeyboard
var eg multierror.Group
func NewKeyboardManager(ctx context.Context, isDockerDesktopActive, isWatchConfigured bool,
sc chan<- os.Signal,
watchFn func(ctx context.Context,
project *types.Project,
services []string,
options api.WatchOptions,
) error,
) {
km := LogKeyboard{}
km.IsDockerDesktopActive = isDockerDesktopActive
km.IsWatchConfigured = isWatchConfigured
km.logLevel = INFO
km.Watch.Watching = false
km.Watch.WatchFn = watchFn
km.signalChannel = sc
KeyboardManager = &km
HideCursor()
}
func (lk *LogKeyboard) PrintKeyboardInfo(printFn func()) {
printFn()
if lk.logLevel == INFO {
lk.printNavigationMenu()
}
}
// Creates space to print error and menu string
func (lk *LogKeyboard) createBuffer(lines int) {
allocateSpace(lines)
if lk.kError.shouldDisplay() {
extraLines := linesOffset(lk.kError.error()) + 1
allocateSpace(extraLines)
lines += extraLines
}
infoMessage := lk.navigationMenu()
extraLines := linesOffset(infoMessage) + 1
allocateSpace(extraLines)
lines += extraLines
if lines > 0 {
MoveCursorUp(lines)
}
}
func (lk *LogKeyboard) printNavigationMenu() {
lk.clearNavigationMenu()
lk.createBuffer(0)
if lk.logLevel == INFO {
height := goterm.Height()
menu := lk.navigationMenu()
MoveCursorX(0)
SaveCursor()
lk.kError.printError(height, menu)
MoveCursor(height-linesOffset(menu), 0)
ClearLine()
fmt.Print(menu)
MoveCursorX(0)
RestoreCursor()
}
}
func (lk *LogKeyboard) navigationMenu() string {
var options string
var openDDInfo string
if lk.IsDockerDesktopActive {
openDDInfo = shortcutKeyColor("v") + navColor(" View in Docker Desktop")
}
var watchInfo string
if openDDInfo != "" {
watchInfo = navColor(" ")
}
var isEnabled = " Enable"
if lk.Watch.Watching {
isEnabled = " Disable"
}
watchInfo = watchInfo + shortcutKeyColor("w") + navColor(isEnabled+" Watch")
return options + openDDInfo + watchInfo
}
func (lk *LogKeyboard) clearNavigationMenu() {
height := goterm.Height()
MoveCursorX(0)
SaveCursor()
for i := 0; i < height; i++ {
MoveCursorDown(1)
ClearLine()
}
RestoreCursor()
}
func (lk *LogKeyboard) openDockerDesktop(ctx context.Context, project *types.Project) {
if !lk.IsDockerDesktopActive {
return
}
eg.Go(tracing.EventWrapFuncForErrGroup(ctx, "menu/gui", tracing.SpanOptions{},
func(ctx context.Context) error {
link := fmt.Sprintf("docker-desktop://dashboard/apps/%s", project.Name)
err := open.Run(link)
if err != nil {
err = fmt.Errorf("Could not open Docker Desktop")
lk.keyboardError("View", err)
}
return err
}),
)
}
func (lk *LogKeyboard) keyboardError(prefix string, err error) {
lk.kError.addError(prefix, err)
lk.printNavigationMenu()
timer1 := time.NewTimer((DISPLAY_ERROR_TIME + 1) * time.Second)
go func() {
<-timer1.C
lk.printNavigationMenu()
}()
}
func (lk *LogKeyboard) StartWatch(ctx context.Context, project *types.Project, options api.UpOptions) {
if !lk.IsWatchConfigured {
eg.Go(tracing.EventWrapFuncForErrGroup(ctx, "menu/watch", tracing.SpanOptions{},
func(ctx context.Context) error {
err := fmt.Errorf("Watch is not yet configured. Learn more: %s", ansiColor(CYAN, "https://docs.docker.com/compose/file-watch/"))
lk.keyboardError("Watch", err)
return err
}))
return
}
lk.Watch.switchWatching()
if !lk.Watch.isWatching() {
lk.Watch.Cancel()
} else {
eg.Go(tracing.EventWrapFuncForErrGroup(ctx, "menu/watch", tracing.SpanOptions{},
func(ctx context.Context) error {
lk.Watch.newContext(ctx)
buildOpts := *options.Create.Build
buildOpts.Quiet = true
return lk.Watch.WatchFn(lk.Watch.Ctx, project, options.Start.Services, api.WatchOptions{
Build: &buildOpts,
LogTo: options.Start.Attach,
})
}))
}
}
func (lk *LogKeyboard) KeyboardClose() {
_ = keyboard.Close()
}
func (lk *LogKeyboard) HandleKeyEvents(event keyboard.KeyEvent, ctx context.Context, project *types.Project, options api.UpOptions) {
switch kRune := event.Rune; kRune {
case 'v':
lk.openDockerDesktop(ctx, project)
case 'w':
lk.StartWatch(ctx, project, options)
}
switch key := event.Key; key {
case keyboard.KeyCtrlC:
lk.KeyboardClose()
lk.clearNavigationMenu()
ShowCursor()
lk.logLevel = NONE
if lk.Watch.Watching && lk.Watch.Cancel != nil {
lk.Watch.Cancel()
_ = eg.Wait().ErrorOrNil() // Need to print this ?
}
// will notify main thread to kill and will handle gracefully
lk.signalChannel <- syscall.SIGINT
case keyboard.KeyEnter:
lk.printNavigationMenu()
}
}
func allocateSpace(lines int) {
for i := 0; i < lines; i++ {
ClearLine()
NewLine()
MoveCursorX(0)
}
}
func linesOffset(s string) int {
return int(math.Floor(float64(lenAnsi(s)) / float64(goterm.Width())))
}
func shortcutKeyColor(key string) string {
foreground := "38;2"
black := "0;0;0"
background := "48;2"
white := "255;255;255"
return ansiColor(foreground+";"+black+";"+background+";"+white, key, BOLD)
}

View File

@@ -24,31 +24,38 @@ import (
"github.com/docker/cli/cli-plugins/plugin"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/cmd/cmdtrace"
"github.com/docker/docker/client"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/docker/compose/v2/cmd/compatibility"
commands "github.com/docker/compose/v2/cmd/compose"
"github.com/docker/compose/v2/internal"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/compose"
)
func pluginMain() {
plugin.Run(func(dockerCli command.Cli) *cobra.Command {
serviceProxy := api.NewServiceProxy().WithService(compose.NewComposeService(dockerCli))
cmd := commands.RootCommand(dockerCli, serviceProxy)
originalPreRun := cmd.PersistentPreRunE
// TODO(milas): this cast is safe but we should not need to do this,
// we should expose the concrete service type so that we do not need
// to rely on the `api.Service` interface internally
backend := compose.NewComposeService(dockerCli).(commands.Backend)
cmd := commands.RootCommand(dockerCli, backend)
originalPreRunE := 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, os.Args[1:])
// compose-specific initialization
dockerCliPostInitialize(dockerCli)
if originalPreRun != nil {
return originalPreRun(cmd, args)
if err := cmdtrace.Setup(cmd, dockerCli, os.Args[1:]); err != nil {
logrus.Debugf("failed to enable tracing: %v", err)
}
if originalPreRunE != nil {
return originalPreRunE(cmd, args)
}
return nil
}
@@ -68,6 +75,22 @@ func pluginMain() {
})
}
// dockerCliPostInitialize performs Compose-specific configuration for the
// command.Cli instance provided by the plugin.Run() initialization.
//
// NOTE: This must be called AFTER plugin.PersistentPreRunE.
func dockerCliPostInitialize(dockerCli command.Cli) {
// HACK(milas): remove once docker/cli#4574 is merged; for now,
// set it in a rather roundabout way by grabbing the underlying
// concrete client and manually invoking an option on it
_ = dockerCli.Apply(func(cli *command.DockerCli) error {
if mobyClient, ok := cli.Client().(*client.Client); ok {
_ = client.WithUserAgent("compose/" + internal.Version)(mobyClient)
}
return nil
})
}
func main() {
if plugin.RunningStandalone() {
os.Args = append([]string{"docker"}, compatibility.Convert(os.Args[1:])...)

View File

@@ -1,40 +1,42 @@
# docker compose
<!---MARKER_GEN_START-->
Define and run multi-container applications with Docker.
Define and run multi-container applications with Docker
### Subcommands
| 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. |
| [`scale`](compose_scale.md) | Scale services |
| [`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 |
| [`watch`](compose_watch.md) | Watch build context for service and rebuild/refresh containers when files are updated |
| Name | Description |
|:--------------------------------|:----------------------------------------------------------------------------------------|
| [`attach`](compose_attach.md) | Attach local standard input, output, and error streams to a service's running container |
| [`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 |
| [`scale`](compose_scale.md) | Scale services |
| [`start`](compose_start.md) | Start services |
| [`stats`](compose_stats.md) | Display a live stream of container(s) resource usage statistics |
| [`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 |
| [`watch`](compose_watch.md) | Watch build context for service and rebuild/refresh containers when files are updated |
### Options
@@ -44,7 +46,7 @@ Define and run multi-container applications with Docker.
| `--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. |
| `--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 |

View File

@@ -1,7 +1,7 @@
# docker compose alpha dry-run
<!---MARKER_GEN_START-->
Dry run command allows you to test a command without applying changes.
Dry run command allows you to test a command without applying changes
<!---MARKER_GEN_END-->

View File

@@ -5,10 +5,11 @@ Publish compose application
### Options
| Name | Type | Default | Description |
|:--------------------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--resolve-image-digests` | | | Pin image tags to digests. |
| Name | Type | Default | Description |
|:--------------------------|:---------|:--------|:-------------------------------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--oci-version` | `string` | | OCI Image/Artifact specification version (automatically determined by default) |
| `--resolve-image-digests` | | | Pin image tags to digests |
<!---MARKER_GEN_END-->

View File

@@ -1,14 +1,14 @@
# docker compose alpha scale
<!---MARKER_GEN_START-->
Scale services.
Scale services
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--no-deps` | | | Don't start linked services |
| `--no-deps` | | | Don't start linked services |
<!---MARKER_GEN_END-->

View File

@@ -0,0 +1,17 @@
# docker compose attach
<!---MARKER_GEN_START-->
Attach local standard input, output, and error streams to a service's running container
### Options
| Name | Type | Default | Description |
|:----------------|:---------|:--------|:----------------------------------------------------------|
| `--detach-keys` | `string` | | Override the key sequence for detaching from a container. |
| `--dry-run` | | | Execute command in dry run mode |
| `--index` | `int` | `0` | index of the container if service has multiple replicas. |
| `--no-stdin` | | | Do not attach STDIN |
| `--sig-proxy` | `bool` | `true` | Proxy all received signals to the process |
<!---MARKER_GEN_END-->

View File

@@ -5,24 +5,25 @@ Build or rebuild services
### Options
| 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) |
| 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) |
| `--with-dependencies` | | | Also build dependencies (transitively) |
<!---MARKER_GEN_END-->
## Description
Services are built once and then tagged, by default as `project_service`.
Services are built once and then tagged, by default as `project-service`.
If the Compose file specifies an
[image](https://github.com/compose-spec/compose-spec/blob/master/spec.md#image) name,

View File

@@ -16,14 +16,15 @@ Parse, resolve and render compose file in canonical format
| `--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. |
| `--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. |
| `-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. |
| `--variables` | | | Print model variables and default values. |
| `--volumes` | | | Print the volume names, one per line. |

View File

@@ -10,7 +10,7 @@ Copy files/folders between a service container and the local filesystem
| `-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 |
| `--index` | `int` | `0` | Index of the container if service has multiple replicas |
<!---MARKER_GEN_END-->

View File

@@ -1,19 +1,20 @@
# docker compose create
<!---MARKER_GEN_START-->
Creates containers for a service.
Creates containers for a service
### Options
| Name | Type | Default | Description |
|:-------------------|:--------------|:---------|:----------------------------------------------------------------------------------------------|
| `--build` | | | Build images before starting containers. |
| `--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 policy. |
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed |
| `--no-build` | | | Don't build an image, even if it's policy |
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
| `--pull` | `string` | `policy` | Pull image before running ("always"\|"missing"\|"never"\|"build") |
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file. |
| `--quiet-pull` | | | Pull without printing progress information |
| `--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. |

View File

@@ -5,13 +5,13 @@ Stop and remove containers, networks
### Options
| 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. |
| 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-->

View File

@@ -1,7 +1,7 @@
# docker compose events
<!---MARKER_GEN_START-->
Receive real time events from containers.
Receive real time events from containers
### Options
@@ -33,4 +33,4 @@ With the `--json` flag, a json object is printed one per line with the format:
}
```
The events that can be received using this can be seen [here](https://docs.docker.com/engine/reference/commandline/events/#object-types).
The events that can be received using this can be seen [here](https://docs.docker.com/reference/cli/docker/system/events/#object-types).

View File

@@ -1,20 +1,20 @@
# docker compose exec
<!---MARKER_GEN_START-->
Execute a command in a running container.
Execute a command in a running container
### Options
| Name | Type | Default | Description |
|:------------------|:--------------|:--------|:---------------------------------------------------------------------------------|
| `-d`, `--detach` | | | Detached mode: Run command in the background. |
| `-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. |
| `--index` | `int` | `0` | Index of the container if service has multiple replicas |
| `-T`, `--no-TTY` | `bool` | `true` | 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-->

View File

@@ -5,11 +5,11 @@ List images used by the created containers
### Options
| 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 |
| 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-->

View File

@@ -1,15 +1,15 @@
# docker compose kill
<!---MARKER_GEN_START-->
Force stop service containers.
Force stop service containers
### Options
| 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. |
| 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-->

View File

@@ -8,12 +8,13 @@ View output from containers
| 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. |
| `-f`, `--follow` | | | Follow log output |
| `--index` | `int` | `0` | index of the container if service has multiple replicas |
| `--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. |
| `-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) |
@@ -21,4 +22,4 @@ View output from containers
## Description
Displays log output from services.
Displays log output from services

View File

@@ -5,17 +5,17 @@ List running compose projects
### Options
| 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. |
| 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-->
## Description
Lists running Compose projects.
Lists running Compose projects

View File

@@ -1,14 +1,14 @@
# docker compose port
<!---MARKER_GEN_START-->
Print the public port for a port binding.
Print the public port for a port binding
### Options
| Name | Type | Default | Description |
|:-------------|:---------|:--------|:--------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--index` | `int` | `0` | index of the container if service has multiple replicas |
| `--index` | `int` | `0` | Index of the container if service has multiple replicas |
| `--protocol` | `string` | `tcp` | tcp or udp |
@@ -16,4 +16,4 @@ Print the public port for a port binding.
## Description
Prints the public port for a port binding.
Prints the public port for a port binding

View File

@@ -9,9 +9,10 @@ List containers
|:----------------------|:--------------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-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). |
| [`--filter`](#filter) | `string` | | Filter services by a property (supported filters: status) |
| [`--format`](#format) | `string` | `table` | Format output using a custom template:<br>'table': Print output in table format with column headers (default)<br>'table TEMPLATE': Print output in table format using the given Go template<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
| `--no-trunc` | | | Don't truncate output |
| `--orphans` | `bool` | `true` | Include orphaned services (not declared by project) |
| `-q`, `--quiet` | | | Only display IDs |
| `--services` | | | Display services |
| [`--status`](#status) | `stringArray` | | Filter services by status. Values: [paused \| restarting \| removing \| running \| dead \| created \| exited] |

View File

@@ -5,22 +5,21 @@ Pull service images
### Options
| 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. |
| `--policy` | `string` | | Apply pull policy ("missing"\|"always"). |
| `-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 |
| `--policy` | `string` | | Apply pull policy ("missing"\|"always") |
| `-q`, `--quiet` | | | Pull without printing progress information |
<!---MARKER_GEN_END-->
## Description
Pulls an image associated with a service defined in a `compose.yaml` file, but does not start containers based on
those images.
Pulls an image associated with a service defined in a `compose.yaml` file, but does not start containers based on those images
## Examples

View File

@@ -8,7 +8,7 @@ Restart service containers
| Name | Type | Default | Description |
|:------------------|:------|:--------|:--------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--no-deps` | | | Don't restart dependent services. |
| `--no-deps` | | | Don't restart dependent services |
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |

View File

@@ -1,33 +1,33 @@
# docker compose run
<!---MARKER_GEN_START-->
Run a one-off command on a service.
Run a one-off command on a service
### Options
| 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 |
| 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` | `bool` | `true` | 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` | `bool` | `true` | 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 |
| `-P`, `--service-ports` | | | Run command with all 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-->

View File

@@ -8,7 +8,7 @@ Scale services
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--no-deps` | | | Don't start linked services. |
| `--no-deps` | | | Don't start linked services |
<!---MARKER_GEN_END-->

View File

@@ -14,4 +14,4 @@ Start services
## Description
Starts existing containers for a service.
Starts existing containers for a service

View File

@@ -0,0 +1,18 @@
# docker compose stats
<!---MARKER_GEN_START-->
Display a live stream of container(s) resource usage statistics
### Options
| Name | Type | Default | Description |
|:--------------|:---------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-a`, `--all` | | | Show all containers (default shows just running) |
| `--dry-run` | | | Execute command in dry run mode |
| `--format` | `string` | | Format output using a custom template:<br>'table': Print output in table format with column headers (default)<br>'table TEMPLATE': Print output in table format using the given Go template<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
| `--no-stream` | | | Disable streaming stats and only pull the first result |
| `--no-trunc` | | | Do not truncate output |
<!---MARKER_GEN_END-->

View File

@@ -14,7 +14,7 @@ Display the running processes
## Description
Displays the running processes.
Displays the running processes
## Examples

View File

@@ -14,4 +14,4 @@ Unpause services
## Description
Unpauses paused containers of a service.
Unpauses paused containers of a service

View File

@@ -5,33 +5,34 @@ 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` | | Restrict attaching to the specified services. Incompatible with --attach-dependencies. |
| `--attach-dependencies` | | | Automatically attach to log output of dependent services. |
| `--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` | | Do not attach (stream logs) to the specified services. |
| `--no-build` | | | Don't build an image, even if it's policy. |
| `--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` | `policy` | 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` | Maximum duration to wait for the project to be running\|healthy. |
| 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` | | Restrict attaching to the specified services. Incompatible with --attach-dependencies. |
| `--attach-dependencies` | | | Automatically attach to log output of dependent services |
| `--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` | | Do not attach (stream logs) to the specified services |
| `--no-build` | | | Don't build an image, even if it's policy |
| `--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` | `policy` | 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` | Maximum duration to wait for the project to be running\|healthy |
| `-w`, `--watch` | | | Watch source code and rebuild/refresh containers when files are updated. |
<!---MARKER_GEN_END-->

View File

@@ -9,7 +9,7 @@ Show the Docker Compose version information
|:-----------------|:---------|:--------|:---------------------------------------------------------------|
| `--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. |
| `--short` | | | Shows only Compose's version number |
<!---MARKER_GEN_END-->

View File

@@ -146,6 +146,7 @@ usage: docker compose
pname: docker
plink: docker.yaml
cname:
- docker compose attach
- docker compose build
- docker compose config
- docker compose cp
@@ -167,6 +168,7 @@ cname:
- docker compose run
- docker compose scale
- docker compose start
- docker compose stats
- docker compose stop
- docker compose top
- docker compose unpause
@@ -175,6 +177,7 @@ cname:
- docker compose wait
- docker compose watch
clink:
- docker_compose_attach.yaml
- docker_compose_build.yaml
- docker_compose_config.yaml
- docker_compose_cp.yaml
@@ -196,6 +199,7 @@ clink:
- docker_compose_run.yaml
- docker_compose_scale.yaml
- docker_compose_start.yaml
- docker_compose_stats.yaml
- docker_compose_stop.yaml
- docker_compose_top.yaml
- docker_compose_unpause.yaml
@@ -238,7 +242,7 @@ options:
- option: env-file
value_type: stringArray
default_value: '[]'
description: Specify an alternate environment file.
description: Specify an alternate environment file
deprecated: false
hidden: false
experimental: false

View File

@@ -6,11 +6,9 @@ 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

View File

@@ -5,10 +5,20 @@ usage: docker compose alpha publish [OPTIONS] [REPOSITORY]
pname: docker compose alpha
plink: docker_compose_alpha.yaml
options:
- option: oci-version
value_type: string
description: |
OCI Image/Artifact specification version (automatically determined by default)
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.
description: Pin image tags to digests
deprecated: false
hidden: false
experimental: false

View File

@@ -0,0 +1,66 @@
command: docker compose attach
short: |
Attach local standard input, output, and error streams to a service's running container
long: |
Attach local standard input, output, and error streams to a service's running container
usage: docker compose attach [OPTIONS] SERVICE
pname: docker compose
plink: docker_compose.yaml
options:
- option: detach-keys
value_type: string
description: Override the key sequence for detaching from a container.
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: index
value_type: int
default_value: "0"
description: index of the container if service has multiple replicas.
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: no-stdin
value_type: bool
default_value: "false"
description: Do not attach STDIN
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: sig-proxy
value_type: bool
default_value: "true"
description: Proxy all received signals to the process
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

View File

@@ -1,7 +1,7 @@
command: docker compose build
short: Build or rebuild services
long: |-
Services are built once and then tagged, by default as `project_service`.
Services are built once and then tagged, by default as `project-service`.
If the Compose file specifies an
[image](https://github.com/compose-spec/compose-spec/blob/master/spec.md#image) name,
@@ -17,7 +17,7 @@ options:
- option: build-arg
value_type: stringArray
default_value: '[]'
description: Set build-time variables for services.
description: Set build-time variables for services
deprecated: false
hidden: false
experimental: false
@@ -26,7 +26,7 @@ options:
swarm: false
- option: builder
value_type: string
description: Set builder to use.
description: Set builder to use
deprecated: false
hidden: false
experimental: false
@@ -109,7 +109,7 @@ options:
- option: pull
value_type: bool
default_value: "false"
description: Always attempt to pull a newer version of the image.
description: Always attempt to pull a newer version of the image
deprecated: false
hidden: false
experimental: false
@@ -119,7 +119,7 @@ options:
- option: push
value_type: bool
default_value: "false"
description: Push service images.
description: Push service images
deprecated: false
hidden: false
experimental: false
@@ -147,6 +147,16 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: with-dependencies
value_type: bool
default_value: "false"
description: Also build dependencies (transitively)
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
inherited_options:
- option: dry-run
value_type: bool

View File

@@ -52,7 +52,7 @@ options:
- option: no-interpolate
value_type: bool
default_value: "false"
description: Don't interpolate environment variables.
description: Don't interpolate environment variables
deprecated: false
hidden: false
experimental: false
@@ -62,7 +62,7 @@ options:
- option: no-normalize
value_type: bool
default_value: "false"
description: Don't normalize compose model.
description: Don't normalize compose model
deprecated: false
hidden: false
experimental: false
@@ -72,7 +72,7 @@ options:
- option: no-path-resolution
value_type: bool
default_value: "false"
description: Don't resolve file paths.
description: Don't resolve file paths
deprecated: false
hidden: false
experimental: false
@@ -103,7 +103,7 @@ options:
shorthand: q
value_type: bool
default_value: "false"
description: Only validate the configuration, don't print anything.
description: Only validate the configuration, don't print anything
deprecated: false
hidden: false
experimental: false
@@ -113,7 +113,7 @@ options:
- option: resolve-image-digests
value_type: bool
default_value: "false"
description: Pin image tags to digests.
description: Pin image tags to digests
deprecated: false
hidden: false
experimental: false
@@ -130,6 +130,16 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: variables
value_type: bool
default_value: "false"
description: Print model variables and default values.
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: volumes
value_type: bool
default_value: "false"

View File

@@ -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,7 +42,7 @@ options:
- option: index
value_type: int
default_value: "0"
description: index of the container if service has multiple replicas
description: Index of the container if service has multiple replicas
deprecated: false
hidden: false
experimental: false

View File

@@ -1,6 +1,6 @@
command: docker compose create
short: Creates containers for a service.
long: Creates containers for a service.
short: Creates containers for a service
long: Creates containers for a service
usage: docker compose create [OPTIONS] [SERVICE...]
pname: docker compose
plink: docker_compose.yaml
@@ -8,7 +8,7 @@ options:
- option: build
value_type: bool
default_value: "false"
description: Build images before starting containers.
description: Build images before starting containers
deprecated: false
hidden: false
experimental: false
@@ -19,7 +19,7 @@ options:
value_type: bool
default_value: "false"
description: |
Recreate containers even if their configuration and image haven't changed.
Recreate containers even if their configuration and image haven't changed
deprecated: false
hidden: false
experimental: false
@@ -29,7 +29,7 @@ options:
- option: no-build
value_type: bool
default_value: "false"
description: Don't build an image, even if it's policy.
description: Don't build an image, even if it's policy
deprecated: false
hidden: false
experimental: false
@@ -57,10 +57,20 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: quiet-pull
value_type: bool
default_value: "false"
description: Pull without printing progress information
deprecated: false
hidden: false
experimental: false
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.
description: Remove containers for services not defined in the Compose file
deprecated: false
hidden: false
experimental: false

View File

@@ -21,7 +21,7 @@ options:
- option: remove-orphans
value_type: bool
default_value: "false"
description: Remove containers for services not defined in the Compose file.
description: Remove containers for services not defined in the Compose file
deprecated: false
hidden: false
experimental: false
@@ -54,7 +54,7 @@ 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

View File

@@ -1,5 +1,5 @@
command: docker compose events
short: Receive real time events from containers.
short: Receive real time events from containers
long: |-
Stream container events for every container in the project.
@@ -19,7 +19,7 @@ long: |-
}
```
The events that can be received using this can be seen [here](/engine/reference/commandline/events/#object-types).
The events that can be received using this can be seen [here](/reference/cli/docker/system/events/#object-types).
usage: docker compose events [OPTIONS] [SERVICE...]
pname: docker compose
plink: docker_compose.yaml

View File

@@ -1,5 +1,5 @@
command: docker compose exec
short: Execute a command in a running container.
short: Execute a command in a running container
long: |-
This is the equivalent of `docker exec` targeting a Compose service.
@@ -13,7 +13,7 @@ options:
shorthand: d
value_type: bool
default_value: "false"
description: 'Detached mode: Run command in the background.'
description: 'Detached mode: Run command in the background'
deprecated: false
hidden: false
experimental: false
@@ -34,7 +34,7 @@ options:
- option: index
value_type: int
default_value: "0"
description: index of the container if service has multiple replicas
description: Index of the container if service has multiple replicas
deprecated: false
hidden: false
experimental: false
@@ -45,7 +45,7 @@ options:
shorthand: i
value_type: bool
default_value: "true"
description: Keep STDIN open even if not attached.
description: Keep STDIN open even if not attached
deprecated: false
hidden: true
experimental: false
@@ -67,7 +67,7 @@ options:
- option: privileged
value_type: bool
default_value: "false"
description: Give extended privileges to the process.
description: Give extended privileges to the process
deprecated: false
hidden: false
experimental: false
@@ -78,7 +78,7 @@ options:
shorthand: t
value_type: bool
default_value: "true"
description: Allocate a pseudo-TTY.
description: Allocate a pseudo-TTY
deprecated: false
hidden: true
experimental: false
@@ -88,7 +88,7 @@ options:
- option: user
shorthand: u
value_type: string
description: Run the command as this user.
description: Run the command as this user
deprecated: false
hidden: false
experimental: false
@@ -98,7 +98,7 @@ options:
- option: workdir
shorthand: w
value_type: string
description: Path to workdir directory for this command.
description: Path to workdir directory for this command
deprecated: false
hidden: false
experimental: false

View File

@@ -8,7 +8,7 @@ options:
- option: format
value_type: string
default_value: table
description: 'Format the output. Values: [table | json].'
description: 'Format the output. Values: [table | json]'
deprecated: false
hidden: false
experimental: false

View File

@@ -1,5 +1,5 @@
command: docker compose kill
short: Force stop service containers.
short: Force stop service containers
long: |-
Forces running containers to stop by sending a `SIGKILL` signal. Optionally the signal can be passed, for example:
@@ -13,7 +13,7 @@ options:
- option: remove-orphans
value_type: bool
default_value: "false"
description: Remove containers for services not defined in the Compose file.
description: Remove containers for services not defined in the Compose file
deprecated: false
hidden: false
experimental: false
@@ -24,7 +24,7 @@ options:
shorthand: s
value_type: string
default_value: SIGKILL
description: SIGNAL to send to the container.
description: SIGNAL to send to the container
deprecated: false
hidden: false
experimental: false

View File

@@ -1,6 +1,6 @@
command: docker compose logs
short: View output from containers
long: Displays log output from services.
long: Displays log output from services
usage: docker compose logs [OPTIONS] [SERVICE...]
pname: docker compose
plink: docker_compose.yaml
@@ -9,7 +9,17 @@ options:
shorthand: f
value_type: bool
default_value: "false"
description: Follow log output.
description: Follow log output
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: index
value_type: int
default_value: "0"
description: index of the container if service has multiple replicas
deprecated: false
hidden: false
experimental: false
@@ -19,7 +29,7 @@ options:
- option: no-color
value_type: bool
default_value: "false"
description: Produce monochrome output.
description: Produce monochrome output
deprecated: false
hidden: false
experimental: false
@@ -29,7 +39,7 @@ options:
- option: no-log-prefix
value_type: bool
default_value: "false"
description: Don't print prefix in logs.
description: Don't print prefix in logs
deprecated: false
hidden: false
experimental: false
@@ -51,7 +61,7 @@ options:
value_type: string
default_value: all
description: |
Number of lines to show from the end of the logs for each container.
Number of lines to show from the end of the logs for each container
deprecated: false
hidden: false
experimental: false
@@ -62,7 +72,7 @@ options:
shorthand: t
value_type: bool
default_value: "false"
description: Show timestamps.
description: Show timestamps
deprecated: false
hidden: false
experimental: false

View File

@@ -1,6 +1,6 @@
command: docker compose ls
short: List running compose projects
long: Lists running Compose projects.
long: Lists running Compose projects
usage: docker compose ls [OPTIONS]
pname: docker compose
plink: docker_compose.yaml
@@ -18,7 +18,7 @@ options:
swarm: false
- option: filter
value_type: filter
description: Filter output based on conditions provided.
description: Filter output based on conditions provided
deprecated: false
hidden: false
experimental: false
@@ -28,7 +28,7 @@ options:
- option: format
value_type: string
default_value: table
description: 'Format the output. Values: [table | json].'
description: 'Format the output. Values: [table | json]'
deprecated: false
hidden: false
experimental: false
@@ -39,7 +39,7 @@ options:
shorthand: q
value_type: bool
default_value: "false"
description: Only display IDs.
description: Only display IDs
deprecated: false
hidden: false
experimental: false

View File

@@ -1,6 +1,6 @@
command: docker compose port
short: Print the public port for a port binding.
long: Prints the public port for a port binding.
short: Print the public port for a port binding
long: Prints the public port for a port binding
usage: docker compose port [OPTIONS] SERVICE PRIVATE_PORT
pname: docker compose
plink: docker_compose.yaml
@@ -8,7 +8,7 @@ options:
- option: index
value_type: int
default_value: "0"
description: index of the container if service has multiple replicas
description: Index of the container if service has multiple replicas
deprecated: false
hidden: false
experimental: false

View File

@@ -35,7 +35,7 @@ options:
swarm: false
- option: filter
value_type: string
description: 'Filter services by a property (supported filters: status).'
description: 'Filter services by a property (supported filters: status)'
details_url: '#filter'
deprecated: false
hidden: false
@@ -70,6 +70,16 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: orphans
value_type: bool
default_value: "true"
description: Include orphaned services (not declared by project)
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: quiet
shorthand: q
value_type: bool

Some files were not shown because too many files have changed in this diff Show More