Jelajahi Sumber

Merge branch 'v2' into 8768-avoid-pulling-same-image-multiple-times

Vedant Koditkar 3 tahun lalu
induk
melakukan
e623b5ca1e
100 mengubah file dengan 2518 tambahan dan 2220 penghapusan
  1. 0 63
      .github/workflows/artifacts.yml
  2. 33 53
      .github/workflows/ci.yml
  3. 1 1
      .github/workflows/docs.yml
  4. 0 11
      .github/workflows/pr-closed.yml
  5. 1 1
      .github/workflows/rebase.yml
  6. 10 16
      .github/workflows/release.yaml
  7. 12 0
      .golangci.yml
  8. 39 3
      BUILDING.md
  9. 4 3
      CONTRIBUTING.md
  10. 7 5
      Dockerfile
  11. 11 2
      Makefile
  12. 1 1
      cmd/compose/build.go
  13. 37 21
      cmd/compose/compose.go
  14. 1 1
      cmd/compose/convert.go
  15. 16 2
      cmd/compose/create.go
  16. 6 14
      cmd/compose/down.go
  17. 3 3
      cmd/compose/events.go
  18. 1 1
      cmd/compose/exec.go
  19. 1 1
      cmd/compose/images.go
  20. 3 3
      cmd/compose/kill.go
  21. 13 12
      cmd/compose/list.go
  22. 1 1
      cmd/compose/logs.go
  23. 6 4
      cmd/compose/pause.go
  24. 1 1
      cmd/compose/port.go
  25. 4 3
      cmd/compose/ps.go
  26. 1 1
      cmd/compose/pull.go
  27. 1 1
      cmd/compose/push.go
  28. 6 4
      cmd/compose/remove.go
  29. 5 4
      cmd/compose/restart.go
  30. 2 2
      cmd/compose/run.go
  31. 3 2
      cmd/compose/start.go
  32. 4 3
      cmd/compose/stop.go
  33. 15 12
      cmd/compose/up.go
  34. 7 2
      cmd/compose/version.go
  35. 12 12
      cmd/formatter/logs.go
  36. 2 2
      docs/Dockerfile
  37. 1 1
      docs/reference/compose.md
  38. 1 1
      docs/reference/compose_convert.md
  39. 1 0
      docs/reference/compose_create.md
  40. 1 1
      docs/reference/compose_down.md
  41. 1 1
      docs/reference/compose_pull.md
  42. 2 2
      docs/reference/compose_restart.md
  43. 1 1
      docs/reference/compose_run.md
  44. 1 0
      docs/reference/compose_up.md
  45. 239 239
      docs/reference/docker_compose.yaml
  46. 121 121
      docs/reference/docker_compose_build.yaml
  47. 116 116
      docs/reference/docker_compose_convert.yaml
  48. 46 45
      docs/reference/docker_compose_cp.yaml
  49. 53 43
      docs/reference/docker_compose_create.yaml
  50. 53 53
      docs/reference/docker_compose_down.yaml
  51. 27 27
      docs/reference/docker_compose_events.yaml
  52. 101 101
      docs/reference/docker_compose_exec.yaml
  53. 12 12
      docs/reference/docker_compose_images.yaml
  54. 16 16
      docs/reference/docker_compose_kill.yaml
  55. 74 74
      docs/reference/docker_compose_logs.yaml
  56. 42 42
      docs/reference/docker_compose_ls.yaml
  57. 1 1
      docs/reference/docker_compose_pause.yaml
  58. 21 21
      docs/reference/docker_compose_port.yaml
  59. 146 146
      docs/reference/docker_compose_ps.yaml
  60. 91 91
      docs/reference/docker_compose_pull.yaml
  61. 25 25
      docs/reference/docker_compose_push.yaml
  62. 21 21
      docs/reference/docker_compose_restart.yaml
  63. 56 56
      docs/reference/docker_compose_rm.yaml
  64. 216 217
      docs/reference/docker_compose_run.yaml
  65. 13 13
      docs/reference/docker_compose_stop.yaml
  66. 6 6
      docs/reference/docker_compose_top.yaml
  67. 231 221
      docs/reference/docker_compose_up.yaml
  68. 21 21
      docs/reference/docker_compose_version.yaml
  69. 12 13
      go.mod
  70. 24 20
      go.sum
  71. 24 1
      pkg/api/api.go
  72. 1 1
      pkg/api/errors.go
  73. 2 2
      pkg/compose/attach.go
  74. 64 55
      pkg/compose/build.go
  75. 7 6
      pkg/compose/build_classic.go
  76. 2 24
      pkg/compose/compose.go
  77. 7 6
      pkg/compose/convergence.go
  78. 1 1
      pkg/compose/cp.go
  79. 23 19
      pkg/compose/create.go
  80. 29 9
      pkg/compose/create_test.go
  81. 14 9
      pkg/compose/down.go
  82. 3 3
      pkg/compose/down_test.go
  83. 68 0
      pkg/compose/envresolver.go
  84. 115 0
      pkg/compose/envresolver_test.go
  85. 1 1
      pkg/compose/hash.go
  86. 9 2
      pkg/compose/kill_test.go
  87. 1 1
      pkg/compose/logs.go
  88. 2 2
      pkg/compose/ls.go
  89. 2 2
      pkg/compose/metrics.go
  90. 10 2
      pkg/compose/pause.go
  91. 5 5
      pkg/compose/printer.go
  92. 13 0
      pkg/compose/ps.go
  93. 3 0
      pkg/compose/ps_test.go
  94. 5 1
      pkg/compose/remove.go
  95. 9 11
      pkg/compose/restart.go
  96. 4 7
      pkg/compose/run.go
  97. 1 1
      pkg/compose/secrets.go
  98. 19 5
      pkg/compose/stop.go
  99. 7 1
      pkg/compose/stop_test.go
  100. 4 4
      pkg/compose/up.go

+ 0 - 63
.github/workflows/artifacts.yml

@@ -1,63 +0,0 @@
-name: Publish Artifacts
-on:
-  issue_comment:
-    types: [created]
-jobs:
-  publish-artifacts:
-    if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/generate-artifacts')
-    runs-on: ubuntu-latest
-    steps:
-      - name: Set up Go 1.18
-        uses: actions/setup-go@v2
-        with:
-          go-version: 1.18.3
-        id: go
-
-      - name: Checkout code into the Go module directory
-        uses: actions/checkout@v2
-
-      - uses: actions/cache@v2
-        with:
-          path: ~/go/pkg/mod
-          key: go-${{ hashFiles('**/go.sum') }}
-
-      - name: Build cross platform compose-plugin binaries
-        run: make -f builder.Makefile cross
-
-      - name: Upload macos-amd64 binary
-        uses: actions/upload-artifact@v2
-        with:
-          name: docker-compose-darwin-amd64
-          path: ${{ github.workspace }}/bin/docker-compose-darwin-amd64
-
-      - name: Upload macos-arm64 binary
-        uses: actions/upload-artifact@v2
-        with:
-          name: docker-compose-darwin-arm64
-          path: ${{ github.workspace }}/bin/docker-compose-darwin-arm64
-
-      - name: Upload linux-amd64 binary
-        uses: actions/upload-artifact@v2
-        with:
-          name: docker-compose-linux-amd64
-          path: ${{ github.workspace }}/bin/docker-compose-linux-amd64
-
-      - name: Upload linux-ppc64le binary
-        uses: actions/upload-artifact@v2
-        with:
-          name: docker-compose-linux-ppc64le
-          path: ${{ github.workspace }}/bin/docker-compose-linux-ppc64le
-
-      - name: Upload windows-amd64 binary
-        uses: actions/upload-artifact@v2
-        with:
-          name: docker-compose-windows-amd64.exe
-          path: ${{ github.workspace }}/bin/docker-compose-windows-amd64.exe
-
-      - name: Update comment
-        uses: peter-evans/create-or-update-comment@v1
-        with:
-          comment-id: ${{ github.event.comment.id }}
-          body: |
-            This PR can be tested using [binaries](https://github.com/docker/compose-cli/actions/runs/${{ github.run_id }}).
-          reactions: eyes

+ 33 - 53
.github/workflows/ci.yml

@@ -11,22 +11,22 @@ on:
         description: 'To run with tmate enter "debug_enabled"'
         required: false
         default: "false"
-
+env:
+  GO_VERSION: 1.18.5
+  DOCKER_CLI_VERSION: 20.10.17
 jobs:
   lint:
     name: Lint
     runs-on: ubuntu-latest
-    env:
-      GO111MODULE: "on"
     steps:
-      - name: Set up Go 1.18
-        uses: actions/setup-go@v2
-        with:
-          go-version: 1.18.3
-        id: go
-
       - name: Checkout code into the Go module directory
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
+
+      - name: Set up Go ${{ env.GO_VERSION }}
+        uses: actions/setup-go@v3
+        with:
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
 
       - name: Validate go-mod, license headers and docs are up-to-date
         run: make validate
@@ -34,8 +34,9 @@ jobs:
       - name: Run golangci-lint
         env:
           BUILD_TAGS: e2e
-        uses: golangci/golangci-lint-action@v2
+        uses: golangci/golangci-lint-action@v3
         with:
+          version: v1.47.3
           args: --timeout=180s
 
   # only on main branch, costs too much for the gain on every PR
@@ -43,22 +44,15 @@ jobs:
     name: Validate cross build
     runs-on: ubuntu-latest
     if: github.ref == 'refs/heads/main'
-    env:
-      GO111MODULE: "on"
     steps:
-      - name: Set up Go 1.18
-        uses: actions/setup-go@v2
-        with:
-          go-version: 1.18.3
-        id: go
-
       - name: Checkout code into the Go module directory
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
 
-      - uses: actions/cache@v2
+      - name: Set up Go ${{ env.GO_VERSION }}
+        uses: actions/setup-go@v3
         with:
-          path: ~/go/pkg/mod
-          key: go-${{ hashFiles('**/go.sum') }}
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
 
       # Ensure we don't discover cross platform build issues at release time.
       # Time used to build linux here is gained back in the build for local E2E step
@@ -68,28 +62,21 @@ jobs:
   build-plugin:
     name: Build and tests in plugin mode
     runs-on: ubuntu-latest
-    env:
-      GO111MODULE: "on"
     steps:
-      - name: Set up Go 1.18
-        uses: actions/setup-go@v2
+      - name: Checkout code into the Go module directory
+        uses: actions/checkout@v3
+
+      - name: Set up Go ${{ env.GO_VERSION }}
+        uses: actions/setup-go@v3
         with:
-          go-version: 1.18.3
-        id: go
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
 
       - name: Setup docker CLI
         run: |
-          curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.3.tgz | tar xz
+          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: Checkout code into the Go module directory
-        uses: actions/checkout@v2
-
-      - uses: actions/cache@v2
-        with:
-          path: ~/go/pkg/mod
-          key: go-${{ hashFiles('**/go.sum') }}
-
       - name: Test
         run: make -f builder.Makefile test
 
@@ -104,28 +91,21 @@ jobs:
   build-standalone:
     name: Build and tests in standalone mode
     runs-on: ubuntu-latest
-    env:
-      GO111MODULE: "on"
     steps:
-      - name: Set up Go 1.18
-        uses: actions/setup-go@v2
+      - name: Checkout code into the Go module directory
+        uses: actions/checkout@v3
+
+      - name: Set up Go ${{ env.GO_VERSION }}
+        uses: actions/setup-go@v3
         with:
-          go-version: 1.18.3
-        id: go
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
 
       - name: Setup docker CLI
         run: |
-          curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.3.tgz | tar xz
+          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: Checkout code into the Go module directory
-        uses: actions/checkout@v2
-
-      - uses: actions/cache@v2
-        with:
-          path: ~/go/pkg/mod
-          key: go-${{ hashFiles('**/go.sum') }}
-
       - name: Build for local E2E
         env:
           BUILD_TAGS: e2e

+ 1 - 1
.github/workflows/docs.yml

@@ -40,6 +40,7 @@ jobs:
         uses: peter-evans/create-pull-request@923ad837f191474af6b1721408744feb989a4c27 # v4.0.4
         with:
           token: ${{ secrets.GHPAT_DOCS_DISPATCH }}
+          push-to-fork: docker-tools-robot/docker.github.io
           commit-message: Update Compose reference API to ${{ github.event.release.name }}
           signoff: true
           branch: dispatch/compose-api-reference-${{ github.event.release.name }}
@@ -47,5 +48,4 @@ jobs:
           title: Update Compose reference API to ${{ github.event.release.name }}
           body: |
             Update the Compose reference API documentation to keep in sync with the latest release `${{ github.event.release.name }}`
-          labels: area/Compose
           draft: false

+ 0 - 11
.github/workflows/pr-closed.yml

@@ -1,11 +0,0 @@
-name: PR cleanup
-on:
-  pull_request:
-    types: [closed]
-jobs:
-  delete_pr_artifacts:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: stefanluptak/delete-old-pr-artifacts@v1
-        with:
-          workflow_filename: ci.yaml

+ 1 - 1
.github/workflows/rebase.yml

@@ -9,7 +9,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout the latest code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
         with:
           token: ${{ secrets.GITHUB_TOKEN }}
           fetch-depth: 0 # otherwise, you will fail to push refs to dest repo

+ 10 - 16
.github/workflows/release.yaml

@@ -6,32 +6,26 @@ on:
       tag:
         description: "Release Tag"
         required: true
-
+env:
+  GO_VERSION: 1.18.5
 jobs:
   upload-release:
     runs-on: ubuntu-latest
     steps:
-      - name: Set up Go 1.18
-        uses: actions/setup-go@v2
+      - name: Checkout code into the Go module directory
+        uses: actions/checkout@v3
+
+      - name: Set up Go ${{ env.GO_VERSION }}
+        uses: actions/setup-go@v3
         with:
-          go-version: 1.18.3
-        id: go
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
 
       - name: Setup docker CLI
         run: |
-          curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.3.tgz | tar xz
+          curl https://download.docker.com/linux/static/stable/x86_64/docker-20.10.17.tgz | tar xz
           sudo cp ./docker/docker /usr/bin/ && rm -rf docker && docker version
 
-      - name: Checkout code into the Go module directory
-        uses: actions/checkout@v2
-
-      - uses: actions/cache@v2
-        with:
-          path: ~/go/pkg/mod
-          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
-          restore-keys: |
-            ${{ runner.os }}-go-
-
       - name: Build
         run: make GIT_TAG=${{ github.event.inputs.tag }} -f builder.Makefile cross
 

+ 12 - 0
.golangci.yml

@@ -7,6 +7,7 @@ linters:
     - deadcode
     - depguard
     - errcheck
+    - gocritic
     - gocyclo
     - gofmt
     - goimports
@@ -32,6 +33,17 @@ linters-settings:
       # The io/ioutil package has been deprecated.
       # https://go.dev/doc/go1.16#ioutil
       - io/ioutil
+  gocritic:
+    # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
+    # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
+    enabled-tags:
+      - diagnostic
+      - opinionated
+      - style
+    disabled-checks:
+      - paramTypeCombine
+      - unnamedResult
+      - whyNoLint
   gocyclo:
     min-complexity: 16
   lll:

+ 39 - 3
BUILDING.md

@@ -34,15 +34,51 @@ make test
 
 If you need to update a golden file simply do `go test ./... -test.update-golden`.
 
-### End to end tests
+### End-to-end tests
+To run e2e tests, the Compose CLI binary need to be build. All the commands to run e2e tests propose a version
+with the prefix `build-and-e2e` to first build the CLI before executing tests.
 
-To run the end to end tests, run:
+
+Note that this requires a local Docker Engine to be running.
+
+#### Whole end-to-end tests suite
+
+To execute both CLI and standalone e2e tests, run :
+
+```console
+make e2e
+```
+
+Or if you need to build the CLI, run: 
+```console
+make build-and-e2e
+```
+
+#### Plugin end-to-end tests suite
+
+To execute CLI plugin e2e tests, run :
 
 ```console
 make e2e-compose
 ```
 
-Note that this requires a local Docker Engine to be running.
+Or if you need to build the CLI, run:
+```console
+make build-and-e2e-compose
+```
+
+#### Standalone end-to-end tests suite
+
+To execute the standalone CLI e2e tests, run :
+
+```console
+make e2e-compose-standalone
+```
+
+Or if you need to build the CLI, run:
+```console
+make build-and-e2e-compose-standalone
+```
 
 ## Releases
 

+ 4 - 3
CONTRIBUTING.md

@@ -124,9 +124,10 @@ Fork the repository and make changes on your fork in a feature branch:
     issue.
 
 Submit unit tests for your changes. Go has a great test framework built in; use
-it! Take a look at existing tests for inspiration. [Run the full test
-suite](README.md) on your branch before
-submitting a pull request.
+it! Take a look at existing tests for inspiration. Also end-to-end tests are
+available. Run the full test suite, both unit tests and e2e tests on your
+branch before submitting a pull request. See [BUILDING.md](BUILDING.md) for
+instructions to build and run tests.
 
 Write clean code. Universally formatted code promotes ease of writing, reading,
 and maintenance. Always run `gofmt -s -w file.go` on each changed file before

+ 7 - 5
Dockerfile

@@ -1,4 +1,4 @@
-# syntax=docker/dockerfile:1.2
+# syntax=docker/dockerfile:1
 
 
 #   Copyright 2020 Docker Compose CLI authors
@@ -15,10 +15,12 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
-ARG GO_VERSION=1.18.3-alpine
-ARG GOLANGCI_LINT_VERSION=v1.40.1-alpine
+ARG GO_VERSION=1.18.5-alpine
+ARG GOLANGCI_LINT_VERSION=v1.47.3-alpine
 ARG PROTOC_GEN_GO_VERSION=v1.4.3
 
+FROM --platform=${BUILDPLATFORM} golangci/golangci-lint:${GOLANGCI_LINT_VERSION} AS local-golangci-lint
+
 FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS base
 WORKDIR /compose-cli
 RUN apk add --no-cache -vv \
@@ -34,7 +36,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \
 
 FROM base AS lint
 ENV CGO_ENABLED=0
-COPY --from=golangci/golangci-lint /usr/bin/golangci-lint /usr/bin/golangci-lint
+COPY --from=local-golangci-lint /usr/bin/golangci-lint /usr/bin/golangci-lint
 ARG BUILD_TAGS
 ARG GIT_TAG
 RUN --mount=target=. \
@@ -88,7 +90,7 @@ RUN --mount=target=. \
     make -f builder.Makefile test
 
 FROM base AS check-license-headers
-RUN go install github.com/kunalkushwaha/ltag@latest
+RUN go install github.com/google/addlicense@latest
 RUN --mount=target=. \
     make -f builder.Makefile check-license-headers
 

+ 11 - 2
Makefile

@@ -51,6 +51,12 @@ e2e-compose-standalone: ## Run End to end local tests in standalone mode. Set E2
 	docker-compose version
 	go test $(TEST_FLAGS) -v -count=1 -parallel=1 --tags=standalone ./pkg/e2e
 
+.PHONY: build-and-e2e-compose
+build-and-e2e-compose: compose-plugin 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
+
+.PHONY: build-and-e2e-compose-standalone
+build-and-e2e-compose-standalone: compose-plugin e2e-compose-standalone ## Compile the compose cli-plugin and run End to end local tests in standalone mode. Set E2E_TEST=TestName to run a single test
+
 .PHONY: mocks
 mocks:
 	mockgen -destination pkg/mocks/mock_docker_cli.go -package mocks github.com/docker/cli/cli/command Cli
@@ -60,6 +66,9 @@ mocks:
 .PHONY: e2e
 e2e: e2e-compose e2e-compose-standalone ## Run end to end local tests in both modes. Set E2E_TEST=TestName to run a single test
 
+.PHONY: build-and-e2e
+build-and-e2e: compose-plugin e2e-compose e2e-compose-standalone ## Compile the compose cli-plugin and run end to end local tests in both modes. Set E2E_TEST=TestName to run a single test
+
 .PHONY: cross
 cross: ## Compile the CLI for linux, darwin and windows
 	@docker build . --target cross \
@@ -90,7 +99,7 @@ docs: ## generate documentation
 	$(eval $@_TMP_OUT := $(shell mktemp -d -t dockercli-output.XXXXXXXXXX))
 	docker build . \
 	--output type=local,dest=$($@_TMP_OUT) \
-	-f ./docs/docs.Dockerfile \
+	-f ./docs/Dockerfile \
 	--target update
 	rm -rf ./docs/internal
 	cp -R "$($@_TMP_OUT)"/out/* ./docs/
@@ -99,7 +108,7 @@ docs: ## generate documentation
 .PHONY: validate-docs
 validate-docs: ## validate the doc does not change
 	@docker build . \
-	-f ./docs/docs.Dockerfile \
+	-f ./docs/Dockerfile \
 	--target validate
 
 .PHONY: check-dependencies

+ 1 - 1
cmd/compose/build.go

@@ -77,7 +77,7 @@ func buildCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	cmd := &cobra.Command{
-		Use:   "build [SERVICE...]",
+		Use:   "build [OPTIONS] [SERVICE...]",
 		Short: "Build or rebuild services",
 		PreRunE: Adapt(func(ctx context.Context, args []string) error {
 			if opts.memory != "" {

+ 37 - 21
cmd/compose/compose.go

@@ -136,6 +136,24 @@ func (o *projectOptions) addProjectFlags(f *pflag.FlagSet) {
 	_ = f.MarkHidden("workdir")
 }
 
+func (o *projectOptions) projectOrName() (*types.Project, string, error) {
+	name := o.ProjectName
+	var project *types.Project
+	if o.ProjectName == "" {
+		p, err := o.toProject(nil)
+		if err != nil {
+			envProjectName := os.Getenv("COMPOSE_PROJECT_NAME")
+			if envProjectName != "" {
+				return nil, envProjectName, nil
+			}
+			return nil, "", err
+		}
+		project = p
+		name = p.Name
+	}
+	return project, name, nil
+}
+
 func (o *projectOptions) toProjectName() (string, error) {
 	if o.ProjectName != "" {
 		return o.ProjectName, nil
@@ -159,15 +177,15 @@ func (o *projectOptions) toProject(services []string, po ...cli.ProjectOptionsFn
 		return nil, compose.WrapComposeError(err)
 	}
 
+	if o.Compatibility || utils.StringToBool(options.Environment["COMPOSE_COMPATIBILITY"]) {
+		api.Separator = "_"
+	}
+
 	project, err := cli.ProjectFromOptions(options)
 	if err != nil {
 		return nil, compose.WrapComposeError(err)
 	}
 
-	if o.Compatibility || utils.StringToBool(project.Environment["COMPOSE_COMPATIBILITY"]) {
-		compose.Separator = "_"
-	}
-
 	ef := o.EnvFile
 	if ef != "" && !filepath.IsAbs(ef) {
 		ef, err = filepath.Abs(ef)
@@ -239,11 +257,11 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
 		verbose bool
 		version bool
 	)
-	command := &cobra.Command{
+	c := &cobra.Command{
 		Short:            "Docker Compose",
 		Use:              PluginName,
 		TraverseChildren: true,
-		// By default (no Run/RunE in parent command) for typos in subcommands, cobra displays the help of parent command but exit(0) !
+		// By default (no Run/RunE in parent c) for typos in subcommands, cobra displays the help of parent c but exit(0) !
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if len(args) == 0 {
 				return cmd.Help()
@@ -300,7 +318,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
 		},
 	}
 
-	command.AddCommand(
+	c.AddCommand(
 		upCommand(&opts, backend),
 		downCommand(&opts, backend),
 		startCommand(&opts, backend),
@@ -327,16 +345,16 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
 		createCommand(&opts, backend),
 		copyCommand(&opts, backend),
 	)
-	command.Flags().SetInterspersed(false)
-	opts.addProjectFlags(command.Flags())
-	command.Flags().StringVar(&ansi, "ansi", "auto", `Control when to print ANSI control characters ("never"|"always"|"auto")`)
-	command.Flags().BoolVarP(&version, "version", "v", false, "Show the Docker Compose version information")
-	command.Flags().MarkHidden("version") //nolint:errcheck
-	command.Flags().BoolVar(&noAnsi, "no-ansi", false, `Do not print ANSI control characters (DEPRECATED)`)
-	command.Flags().MarkHidden("no-ansi") //nolint:errcheck
-	command.Flags().BoolVar(&verbose, "verbose", false, "Show more output")
-	command.Flags().MarkHidden("verbose") //nolint:errcheck
-	return command
+	c.Flags().SetInterspersed(false)
+	opts.addProjectFlags(c.Flags())
+	c.Flags().StringVar(&ansi, "ansi", "auto", `Control when to print ANSI control characters ("never"|"always"|"auto")`)
+	c.Flags().BoolVarP(&version, "version", "v", false, "Show the Docker Compose version information")
+	c.Flags().MarkHidden("version") //nolint:errcheck
+	c.Flags().BoolVar(&noAnsi, "no-ansi", false, `Do not print ANSI control characters (DEPRECATED)`)
+	c.Flags().MarkHidden("no-ansi") //nolint:errcheck
+	c.Flags().BoolVar(&verbose, "verbose", false, "Show more output")
+	c.Flags().MarkHidden("verbose") //nolint:errcheck
+	return c
 }
 
 func setEnvWithDotEnv(prjOpts *projectOptions) error {
@@ -354,10 +372,8 @@ func setEnvWithDotEnv(prjOpts *projectOptions) error {
 		return err
 	}
 	for k, v := range envFromFile {
-		if _, ok := os.LookupEnv(k); !ok {
-			if err = os.Setenv(k, v); err != nil {
-				return err
-			}
+		if err := os.Setenv(k, v); err != nil { // overwrite the process env with merged OS + env file results
+			return err
 		}
 	}
 	return nil

+ 1 - 1
cmd/compose/convert.go

@@ -58,7 +58,7 @@ func convertCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	}
 	cmd := &cobra.Command{
 		Aliases: []string{"config"},
-		Use:     "convert SERVICES",
+		Use:     "convert [OPTIONS] [SERVICE...]",
 		Short:   "Converts the compose file to platform's canonical format",
 		PreRunE: Adapt(func(ctx context.Context, args []string) error {
 			if opts.quiet {

+ 16 - 2
cmd/compose/create.go

@@ -30,6 +30,8 @@ import (
 type createOptions struct {
 	Build         bool
 	noBuild       bool
+	Pull          string
+	pullChanged   bool
 	removeOrphans bool
 	ignoreOrphans bool
 	forceRecreate bool
@@ -44,9 +46,10 @@ type createOptions struct {
 func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	opts := createOptions{}
 	cmd := &cobra.Command{
-		Use:   "create [SERVICE...]",
+		Use:   "create [OPTIONS] [SERVICE...]",
 		Short: "Creates containers for a service.",
-		PreRunE: Adapt(func(ctx context.Context, args []string) error {
+		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
+			opts.pullChanged = cmd.Flags().Changed("pull")
 			if opts.Build && opts.noBuild {
 				return fmt.Errorf("--build and --no-build are incompatible")
 			}
@@ -56,6 +59,7 @@ func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
 			return nil
 		}),
 		RunE: p.WithProject(func(ctx context.Context, project *types.Project) error {
+			opts.Apply(project)
 			return backend.Create(ctx, project, api.CreateOptions{
 				RemoveOrphans:        opts.removeOrphans,
 				IgnoreOrphans:        opts.ignoreOrphans,
@@ -71,6 +75,7 @@ func createCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	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 missing.")
+	flags.StringVar(&opts.Pull, "pull", "missing", `Pull image before running ("always"|"missing"|"never")`)
 	flags.BoolVar(&opts.forceRecreate, "force-recreate", false, "Recreate containers even if their configuration and image haven't changed.")
 	flags.BoolVar(&opts.noRecreate, "no-recreate", false, "If containers already exist, don't recreate them. Incompatible with --force-recreate.")
 	return cmd
@@ -105,6 +110,12 @@ func (opts createOptions) GetTimeout() *time.Duration {
 }
 
 func (opts createOptions) Apply(project *types.Project) {
+	if opts.pullChanged {
+		for i, service := range project.Services {
+			service.PullPolicy = opts.Pull
+			project.Services[i] = service
+		}
+	}
 	if opts.Build {
 		for i, service := range project.Services {
 			if service.Build == nil {
@@ -117,6 +128,9 @@ func (opts createOptions) Apply(project *types.Project) {
 	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
 		}
 	}

+ 6 - 14
cmd/compose/down.go

@@ -22,7 +22,6 @@ import (
 	"os"
 	"time"
 
-	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/compose/v2/pkg/utils"
 	"github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
@@ -45,7 +44,7 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	downCmd := &cobra.Command{
-		Use:   "down",
+		Use:   "down [OPTIONS]",
 		Short: "Stop and remove containers, networks",
 		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
 			opts.timeChanged = cmd.Flags().Changed("timeout")
@@ -66,11 +65,10 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	removeOrphans := utils.StringToBool(os.Getenv("COMPOSE_REMOVE_ORPHANS"))
 	flags.BoolVar(&opts.removeOrphans, "remove-orphans", removeOrphans, "Remove containers for services not defined in the Compose file.")
 	flags.IntVarP(&opts.timeout, "timeout", "t", 10, "Specify a shutdown timeout in seconds")
-	flags.BoolVarP(&opts.volumes, "volumes", "v", false, " Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers.")
+	flags.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 {
-		switch name {
-		case "volume":
+		if name == "volume" {
 			name = "volumes"
 			logrus.Warn("--volume is deprecated, please use --volumes")
 		}
@@ -80,15 +78,9 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runDown(ctx context.Context, backend api.Service, opts downOptions) error {
-	name := opts.ProjectName
-	var project *types.Project
-	if opts.ProjectName == "" {
-		p, err := opts.toProject(nil)
-		if err != nil {
-			return err
-		}
-		project = p
-		name = p.Name
+	project, name, err := opts.projectOrName()
+	if err != nil {
+		return err
 	}
 
 	var timeout *time.Duration

+ 3 - 3
cmd/compose/events.go

@@ -38,7 +38,7 @@ func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		},
 	}
 	cmd := &cobra.Command{
-		Use:   "events [options] [--] [SERVICE...]",
+		Use:   "events [OPTIONS] [SERVICE...]",
 		Short: "Receive real time events from containers.",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runEvents(ctx, backend, opts, args)
@@ -51,12 +51,12 @@ func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, services []string) error {
-	project, err := opts.toProjectName()
+	name, err := opts.toProjectName()
 	if err != nil {
 		return err
 	}
 
-	return backend.Events(ctx, project, api.EventsOptions{
+	return backend.Events(ctx, name, api.EventsOptions{
 		Services: services,
 		Consumer: func(event api.Event) error {
 			if opts.json {

+ 1 - 1
cmd/compose/exec.go

@@ -50,7 +50,7 @@ func execCommand(p *projectOptions, dockerCli command.Cli, backend api.Service)
 		},
 	}
 	runCmd := &cobra.Command{
-		Use:   "exec [options] [-e KEY=VAL...] [--] SERVICE COMMAND [ARGS...]",
+		Use:   "exec [OPTIONS] SERVICE COMMAND [ARGS...]",
 		Short: "Execute a command in a running container.",
 		Args:  cobra.MinimumNArgs(2),
 		PreRunE: Adapt(func(ctx context.Context, args []string) error {

+ 1 - 1
cmd/compose/images.go

@@ -43,7 +43,7 @@ func imagesCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	imgCmd := &cobra.Command{
-		Use:   "images [SERVICE...]",
+		Use:   "images [OPTIONS] [SERVICE...]",
 		Short: "List images used by the created containers",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runImages(ctx, backend, opts, args)

+ 3 - 3
cmd/compose/kill.go

@@ -34,7 +34,7 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	cmd := &cobra.Command{
-		Use:   "kill [options] [SERVICE...]",
+		Use:   "kill [OPTIONS] [SERVICE...]",
 		Short: "Force stop service containers.",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runKill(ctx, backend, opts, args)
@@ -49,12 +49,12 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runKill(ctx context.Context, backend api.Service, opts killOptions, services []string) error {
-	projectName, err := opts.toProjectName()
+	name, err := opts.toProjectName()
 	if err != nil {
 		return err
 	}
 
-	return backend.Kill(ctx, projectName, api.KillOptions{
+	return backend.Kill(ctx, name, api.KillOptions{
 		Services: services,
 		Signal:   opts.signal,
 	})

+ 13 - 12
cmd/compose/list.go

@@ -39,19 +39,20 @@ type lsOptions struct {
 }
 
 func listCommand(backend api.Service) *cobra.Command {
-	opts := lsOptions{Filter: opts.NewFilterOpt()}
+	lsOpts := lsOptions{Filter: opts.NewFilterOpt()}
 	lsCmd := &cobra.Command{
-		Use:   "ls",
+		Use:   "ls [OPTIONS]",
 		Short: "List running compose projects",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
-			return runList(ctx, backend, opts)
+			return runList(ctx, backend, lsOpts)
 		}),
+		Args:              cobra.NoArgs,
 		ValidArgsFunction: noCompletion(),
 	}
-	lsCmd.Flags().StringVar(&opts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
-	lsCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs.")
-	lsCmd.Flags().Var(&opts.Filter, "filter", "Filter output based on conditions provided.")
-	lsCmd.Flags().BoolVarP(&opts.All, "all", "a", false, "Show all stopped Compose projects")
+	lsCmd.Flags().StringVar(&lsOpts.Format, "format", "pretty", "Format the output. Values: [pretty | 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
 }
@@ -60,18 +61,18 @@ var acceptedListFilters = map[string]bool{
 	"name": true,
 }
 
-func runList(ctx context.Context, backend api.Service, opts lsOptions) error {
-	filters := opts.Filter.Value()
+func runList(ctx context.Context, backend api.Service, lsOpts lsOptions) error {
+	filters := lsOpts.Filter.Value()
 	err := filters.Validate(acceptedListFilters)
 	if err != nil {
 		return err
 	}
 
-	stackList, err := backend.List(ctx, api.ListOptions{All: opts.All})
+	stackList, err := backend.List(ctx, api.ListOptions{All: lsOpts.All})
 	if err != nil {
 		return err
 	}
-	if opts.Quiet {
+	if lsOpts.Quiet {
 		for _, s := range stackList {
 			fmt.Println(s.Name)
 		}
@@ -90,7 +91,7 @@ func runList(ctx context.Context, backend api.Service, opts lsOptions) error {
 	}
 
 	view := viewFromStackList(stackList)
-	return formatter.Print(view, opts.Format, os.Stdout, func(w io.Writer) {
+	return formatter.Print(view, lsOpts.Format, os.Stdout, func(w io.Writer) {
 		for _, stack := range view {
 			_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", stack.Name, stack.Status, stack.ConfigFiles)
 		}

+ 1 - 1
cmd/compose/logs.go

@@ -44,7 +44,7 @@ func logsCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	logsCmd := &cobra.Command{
-		Use:   "logs [SERVICE...]",
+		Use:   "logs [OPTIONS] [SERVICE...]",
 		Short: "View output from containers",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runLogs(ctx, backend, opts, args)

+ 6 - 4
cmd/compose/pause.go

@@ -44,13 +44,14 @@ func pauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runPause(ctx context.Context, backend api.Service, opts pauseOptions, services []string) error {
-	project, err := opts.toProjectName()
+	project, name, err := opts.projectOrName()
 	if err != nil {
 		return err
 	}
 
-	return backend.Pause(ctx, project, api.PauseOptions{
+	return backend.Pause(ctx, name, api.PauseOptions{
 		Services: services,
+		Project:  project,
 	})
 }
 
@@ -74,12 +75,13 @@ func unpauseCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runUnPause(ctx context.Context, backend api.Service, opts unpauseOptions, services []string) error {
-	project, err := opts.toProjectName()
+	project, name, err := opts.projectOrName()
 	if err != nil {
 		return err
 	}
 
-	return backend.UnPause(ctx, project, api.PauseOptions{
+	return backend.UnPause(ctx, name, api.PauseOptions{
 		Services: services,
+		Project:  project,
 	})
 }

+ 1 - 1
cmd/compose/port.go

@@ -38,7 +38,7 @@ func portCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	cmd := &cobra.Command{
-		Use:   "port [options] [--] SERVICE PRIVATE_PORT",
+		Use:   "port [OPTIONS] SERVICE PRIVATE_PORT",
 		Short: "Print the public port for a port binding.",
 		Args:  cobra.MinimumNArgs(2),
 		PreRunE: Adapt(func(ctx context.Context, args []string) error {

+ 4 - 3
cmd/compose/ps.go

@@ -70,7 +70,7 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	psCmd := &cobra.Command{
-		Use:   "ps [SERVICE...]",
+		Use:   "ps [OPTIONS] [SERVICE...]",
 		Short: "List containers",
 		PreRunE: func(cmd *cobra.Command, args []string) error {
 			return opts.parseFilter()
@@ -91,11 +91,12 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runPs(ctx context.Context, backend api.Service, services []string, opts psOptions) error {
-	projectName, err := opts.toProjectName()
+	project, name, err := opts.projectOrName()
 	if err != nil {
 		return err
 	}
-	containers, err := backend.Ps(ctx, projectName, api.PsOptions{
+	containers, err := backend.Ps(ctx, name, api.PsOptions{
+		Project:  project,
 		All:      opts.All,
 		Services: services,
 	})

+ 1 - 1
cmd/compose/pull.go

@@ -43,7 +43,7 @@ func pullCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	cmd := &cobra.Command{
-		Use:   "pull [SERVICE...]",
+		Use:   "pull [OPTIONS] [SERVICE...]",
 		Short: "Pull service images",
 		PreRunE: Adapt(func(ctx context.Context, args []string) error {
 			if opts.noParallel {

+ 1 - 1
cmd/compose/push.go

@@ -36,7 +36,7 @@ func pushCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	pushCmd := &cobra.Command{
-		Use:   "push [SERVICE...]",
+		Use:   "push [OPTIONS] [SERVICE...]",
 		Short: "Push service images",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runPush(ctx, backend, opts, args)

+ 6 - 4
cmd/compose/remove.go

@@ -35,7 +35,7 @@ func removeCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	cmd := &cobra.Command{
-		Use:   "rm [SERVICE...]",
+		Use:   "rm [OPTIONS] [SERVICE...]",
 		Short: "Removes stopped service containers",
 		Long: `Removes stopped service containers
 
@@ -59,23 +59,25 @@ Any data which is not in a volume will be lost.`,
 }
 
 func runRemove(ctx context.Context, backend api.Service, opts removeOptions, services []string) error {
-	project, err := opts.toProjectName()
+	project, name, err := opts.projectOrName()
 	if err != nil {
 		return err
 	}
 
 	if opts.stop {
-		err := backend.Stop(ctx, project, api.StopOptions{
+		err := backend.Stop(ctx, name, api.StopOptions{
 			Services: services,
+			Project:  project,
 		})
 		if err != nil {
 			return err
 		}
 	}
 
-	return backend.Remove(ctx, project, api.RemoveOptions{
+	return backend.Remove(ctx, name, api.RemoveOptions{
 		Services: services,
 		Force:    opts.force,
 		Volumes:  opts.volumes,
+		Project:  project,
 	})
 }

+ 5 - 4
cmd/compose/restart.go

@@ -35,8 +35,8 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	restartCmd := &cobra.Command{
-		Use:   "restart",
-		Short: "Restart containers",
+		Use:   "restart [OPTIONS] [SERVICE...]",
+		Short: "Restart service containers",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runRestart(ctx, backend, opts, args)
 		}),
@@ -49,14 +49,15 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runRestart(ctx context.Context, backend api.Service, opts restartOptions, services []string) error {
-	projectName, err := opts.toProjectName()
+	project, name, err := opts.projectOrName()
 	if err != nil {
 		return err
 	}
 
 	timeout := time.Duration(opts.timeout) * time.Second
-	return backend.Restart(ctx, projectName, api.RestartOptions{
+	return backend.Restart(ctx, name, api.RestartOptions{
 		Timeout:  &timeout,
 		Services: services,
+		Project:  project,
 	})
 }

+ 2 - 2
cmd/compose/run.go

@@ -114,7 +114,7 @@ func runCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *
 		},
 	}
 	cmd := &cobra.Command{
-		Use:   "run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] SERVICE [COMMAND] [ARGS...]",
+		Use:   "run [OPTIONS] SERVICE [COMMAND] [ARGS...]",
 		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 {
@@ -151,7 +151,7 @@ func runCommand(p *projectOptions, dockerCli command.Cli, backend api.Service) *
 	flags.StringArrayVarP(&opts.labels, "label", "l", []string{}, "Add or override a label")
 	flags.BoolVar(&opts.Remove, "rm", false, "Automatically remove the container when it exits")
 	flags.BoolVarP(&opts.noTty, "no-TTY", "T", !dockerCli.Out().IsTerminal(), "Disable pseudo-TTY allocation (default: auto-detected).")
-	flags.StringVar(&opts.name, "name", "", " Assign a name to the container")
+	flags.StringVar(&opts.name, "name", "", "Assign a name to the container")
 	flags.StringVarP(&opts.user, "user", "u", "", "Run as specified username or uid")
 	flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
 	flags.StringVar(&opts.entrypoint, "entrypoint", "", "Override the entrypoint of the image")

+ 3 - 2
cmd/compose/start.go

@@ -43,12 +43,13 @@ func startCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runStart(ctx context.Context, backend api.Service, opts startOptions, services []string) error {
-	projectName, err := opts.toProjectName()
+	project, name, err := opts.projectOrName()
 	if err != nil {
 		return err
 	}
 
-	return backend.Start(ctx, projectName, api.StartOptions{
+	return backend.Start(ctx, name, api.StartOptions{
 		AttachTo: services,
+		Project:  project,
 	})
 }

+ 4 - 3
cmd/compose/stop.go

@@ -36,7 +36,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 	}
 	cmd := &cobra.Command{
-		Use:   "stop [SERVICE...]",
+		Use:   "stop [OPTIONS] [SERVICE...]",
 		Short: "Stop services",
 		PreRun: func(cmd *cobra.Command, args []string) {
 			opts.timeChanged = cmd.Flags().Changed("timeout")
@@ -53,7 +53,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 
 func runStop(ctx context.Context, backend api.Service, opts stopOptions, services []string) error {
-	projectName, err := opts.toProjectName()
+	project, name, err := opts.projectOrName()
 	if err != nil {
 		return err
 	}
@@ -63,8 +63,9 @@ func runStop(ctx context.Context, backend api.Service, opts stopOptions, service
 		timeoutValue := time.Duration(opts.timeout) * time.Second
 		timeout = &timeoutValue
 	}
-	return backend.Stop(ctx, projectName, api.StopOptions{
+	return backend.Stop(ctx, name, api.StopOptions{
 		Timeout:  timeout,
 		Services: services,
+		Project:  project,
 	})
 }

+ 15 - 12
cmd/compose/up.go

@@ -96,7 +96,7 @@ func upCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	up := upOptions{}
 	create := createOptions{}
 	upCmd := &cobra.Command{
-		Use:   "up [SERVICE...]",
+		Use:   "up [OPTIONS] [SERVICE...]",
 		Short: "Create and start containers",
 		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
 			create.timeChanged = cmd.Flags().Changed("timeout")
@@ -115,6 +115,7 @@ func upCommand(p *projectOptions, backend api.Service) *cobra.Command {
 	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 missing.")
+	flags.StringVar(&create.Pull, "pull", "missing", `Pull image before running ("always"|"missing"|"never")`)
 	flags.BoolVar(&create.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
 	flags.StringArrayVar(&up.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.")
 	flags.BoolVar(&up.noColor, "no-color", false, "Produce monochrome output.")
@@ -219,18 +220,20 @@ func runUp(ctx context.Context, backend api.Service, createOptions createOptions
 
 func setServiceScale(project *types.Project, name string, replicas uint64) error {
 	for i, s := range project.Services {
-		if s.Name == name {
-			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
+		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
 	}
 	return fmt.Errorf("unknown service %q", name)
 }

+ 7 - 2
cmd/compose/version.go

@@ -35,13 +35,18 @@ type versionOptions struct {
 func versionCommand() *cobra.Command {
 	opts := versionOptions{}
 	cmd := &cobra.Command{
-		Use:   "version",
+		Use:   "version [OPTIONS]",
 		Short: "Show the Docker Compose version information",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  cobra.NoArgs,
 		RunE: func(cmd *cobra.Command, _ []string) error {
 			runVersion(opts)
 			return nil
 		},
+		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+			// overwrite parent PersistentPreRunE to avoid trying to load
+			// compose file on version command if COMPOSE_FILE is set
+			return nil
+		},
 	}
 	// define flags for backward compatibility with com.docker.cli
 	flags := cmd.Flags()

+ 12 - 12
cmd/formatter/logs.go

@@ -27,6 +27,16 @@ import (
 	"github.com/docker/compose/v2/pkg/api"
 )
 
+// LogConsumer consume logs from services and format them
+type logConsumer struct {
+	ctx        context.Context
+	presenters sync.Map // map[string]*presenter
+	width      int
+	writer     io.Writer
+	color      bool
+	prefix     bool
+}
+
 // NewLogConsumer creates a new LogConsumer
 func NewLogConsumer(ctx context.Context, w io.Writer, color bool, prefix bool) api.LogConsumer {
 	return &logConsumer{
@@ -79,14 +89,14 @@ func (l *logConsumer) Log(container, service, message string) {
 	}
 	p := l.getPresenter(container)
 	for _, line := range strings.Split(message, "\n") {
-		fmt.Fprintf(l.writer, "%s%s\n", p.prefix, line) // nolint:errcheck
+		fmt.Fprintf(l.writer, "%s%s\n", p.prefix, line) //nolint:errcheck
 	}
 }
 
 func (l *logConsumer) Status(container, msg string) {
 	p := l.getPresenter(container)
 	s := p.colors(fmt.Sprintf("%s %s\n", container, msg))
-	l.writer.Write([]byte(s)) // nolint:errcheck
+	l.writer.Write([]byte(s)) //nolint:errcheck
 }
 
 func (l *logConsumer) computeWidth() {
@@ -101,16 +111,6 @@ func (l *logConsumer) computeWidth() {
 	l.width = width + 1
 }
 
-// LogConsumer consume logs from services and format them
-type logConsumer struct {
-	ctx        context.Context
-	presenters sync.Map // map[string]*presenter
-	width      int
-	writer     io.Writer
-	color      bool
-	prefix     bool
-}
-
 type presenter struct {
 	colors colorFunc
 	name   string

+ 2 - 2
docs/docs.Dockerfile → docs/Dockerfile

@@ -1,4 +1,4 @@
-# syntax=docker/dockerfile:1.3-labs
+# syntax=docker/dockerfile:1
 
 
 #   Copyright 2020 Docker Compose CLI authors
@@ -15,7 +15,7 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
-ARG GO_VERSION=1.18.3
+ARG GO_VERSION=1.18.5
 ARG FORMATS=md,yaml
 
 FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS docsgen

+ 1 - 1
docs/reference/compose.md

@@ -23,7 +23,7 @@ Docker Compose
 | [`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 containers |
+| [`restart`](compose_restart.md) | Restart service containers |
 | [`rm`](compose_rm.md) | Removes stopped service containers |
 | [`run`](compose_run.md) | Run a one-off command on a service. |
 | [`start`](compose_start.md) | Start services |

+ 1 - 1
docs/reference/compose_convert.md

@@ -5,7 +5,7 @@ Converts the compose file to platform's canonical format
 
 ### Aliases
 
-`convert`, `config`
+`docker compose convert`, `docker compose config`
 
 ### Options
 

+ 1 - 0
docs/reference/compose_create.md

@@ -11,6 +11,7 @@ Creates containers for a service.
 | `--force-recreate` |  |  | Recreate containers even if their configuration and image haven't changed. |
 | `--no-build` |  |  | Don't build an image, even if it's missing. |
 | `--no-recreate` |  |  | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
+| `--pull` | `string` | `missing` | Pull image before running ("always"\|"missing"\|"never") |
 
 
 <!---MARKER_GEN_END-->

+ 1 - 1
docs/reference/compose_down.md

@@ -10,7 +10,7 @@ Stop and remove containers, networks
 | `--remove-orphans` |  |  | Remove containers for services not defined in the Compose file. |
 | `--rmi` | `string` |  | Remove images used by services. "local" remove only images that don't have a custom tag ("local"\|"all") |
 | `-t`, `--timeout` | `int` | `10` | Specify a shutdown timeout in seconds |
-| `-v`, `--volumes` |  |  |  Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. |
+| `-v`, `--volumes` |  |  | Remove named volumes declared in the `volumes` section of the Compose file and anonymous volumes attached to containers. |
 
 
 <!---MARKER_GEN_END-->

+ 1 - 1
docs/reference/compose_pull.md

@@ -61,4 +61,4 @@ $ docker compose pull db
    ⠹ f63c47038e66 Waiting                                                  9.3s
    ⠹ 77a0c198cde5 Waiting                                                  9.3s
    ⠹ c8752d5b785c Waiting                                                  9.3s
-``̀`
+```

+ 2 - 2
docs/reference/compose_restart.md

@@ -1,7 +1,7 @@
 # docker compose restart
 
 <!---MARKER_GEN_START-->
-Restart containers
+Restart service containers
 
 ### Options
 
@@ -14,7 +14,7 @@ Restart containers
 
 ## Description
 
-Restarts all stopped and running services.
+Restarts all stopped and running services, or the specified services only.
 
 If you make changes to your `compose.yml` configuration, these changes are not reflected
 after running this command. For example, changes to environment variables (which are added

+ 1 - 1
docs/reference/compose_run.md

@@ -12,7 +12,7 @@ Run a one-off command on a service.
 | `-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 |
+| `--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. |

+ 1 - 0
docs/reference/compose_up.md

@@ -21,6 +21,7 @@ Create and start containers
 | `--no-log-prefix` |  |  | Don't print prefix in logs. |
 | `--no-recreate` |  |  | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
 | `--no-start` |  |  | Don't start the services after creating them. |
+| `--pull` | `string` | `missing` | Pull image before running ("always"\|"missing"\|"never") |
 | `--quiet-pull` |  |  | Pull without printing progress information. |
 | `--remove-orphans` |  |  | Remove containers for services not defined in the Compose file. |
 | `-V`, `--renew-anon-volumes` |  |  | Recreate anonymous volumes instead of retrieving data from the previous containers. |

+ 239 - 239
docs/reference/docker_compose.yaml

@@ -1,277 +1,277 @@
 command: docker compose
 short: Docker Compose
 long: |-
-  You can use compose subcommand, `docker compose [-f <arg>...] [options] [COMMAND] [ARGS...]`, to build and manage
-  multiple services in Docker containers.
+    You can use compose subcommand, `docker compose [-f <arg>...] [options] [COMMAND] [ARGS...]`, to build and manage
+    multiple services in Docker containers.
 
-  ### Use `-f` to specify name and path of one or more Compose files
-  Use the `-f` flag to specify the location of a Compose configuration file.
+    ### Use `-f` to specify name and path of one or more Compose files
+    Use the `-f` flag to specify the location of a Compose configuration file.
 
-  #### Specifying multiple Compose files
-  You can supply multiple `-f` configuration files. When you supply multiple files, Compose combines them into a single
-  configuration. Compose builds the configuration in the order you supply the files. Subsequent files override and add
-  to their predecessors.
+    #### Specifying multiple Compose files
+    You can supply multiple `-f` configuration files. When you supply multiple files, Compose combines them into a single
+    configuration. Compose builds the configuration in the order you supply the files. Subsequent files override and add
+    to their predecessors.
 
-  For example, consider this command line:
+    For example, consider this command line:
 
-  ```console
-  $ docker compose -f docker-compose.yml -f docker-compose.admin.yml run backup_db
-  ```
+    ```console
+    $ docker compose -f docker-compose.yml -f docker-compose.admin.yml run backup_db
+    ```
 
-  The `docker-compose.yml` file might specify a `webapp` service.
+    The `docker-compose.yml` file might specify a `webapp` service.
 
-  ```yaml
-  services:
-    webapp:
-      image: examples/web
-      ports:
-        - "8000:8000"
-      volumes:
-        - "/data"
-  ```
-  If the `docker-compose.admin.yml` also specifies this same service, any matching fields override the previous file.
-  New values, add to the `webapp` service configuration.
+    ```yaml
+    services:
+      webapp:
+        image: examples/web
+        ports:
+          - "8000:8000"
+        volumes:
+          - "/data"
+    ```
+    If the `docker-compose.admin.yml` also specifies this same service, any matching fields override the previous file.
+    New values, add to the `webapp` service configuration.
 
-  ```yaml
-  services:
-    webapp:
-      build: .
-      environment:
-        - DEBUG=1
-  ```
+    ```yaml
+    services:
+      webapp:
+        build: .
+        environment:
+          - DEBUG=1
+    ```
 
-  When you use multiple Compose files, all paths in the files are relative to the first configuration file specified
-  with `-f`. You can use the `--project-directory` option to override this base path.
+    When you use multiple Compose files, all paths in the files are relative to the first configuration file specified
+    with `-f`. You can use the `--project-directory` option to override this base path.
 
-  Use a `-f` with `-` (dash) as the filename to read the configuration from stdin. When stdin is used all paths in the
-  configuration are relative to the current working directory.
+    Use a `-f` with `-` (dash) as the filename to read the configuration from stdin. When stdin is used all paths in the
+    configuration are relative to the current working directory.
 
-  The `-f` flag is optional. If you don’t provide this flag on the command line, Compose traverses the working directory
-  and its parent directories looking for a `compose.yaml` or `docker-compose.yaml` file.
+    The `-f` flag is optional. If you don’t provide this flag on the command line, Compose traverses the working directory
+    and its parent directories looking for a `compose.yaml` or `docker-compose.yaml` file.
 
-  #### Specifying a path to a single Compose file
-  You can use the `-f` flag to specify a path to a Compose file that is not located in the current directory, either
-  from the command line or by setting up a `COMPOSE_FILE` environment variable in your shell or in an environment file.
+    #### Specifying a path to a single Compose file
+    You can use the `-f` flag to specify a path to a Compose file that is not located in the current directory, either
+    from the command line or by setting up a `COMPOSE_FILE` environment variable in your shell or in an environment file.
 
-  For an example of using the `-f` option at the command line, suppose you are running the Compose Rails sample, and
-  have a `compose.yaml` file in a directory called `sandbox/rails`. You can use a command like `docker compose pull` to
-  get the postgres image for the db service from anywhere by using the `-f` flag as follows:
+    For an example of using the `-f` option at the command line, suppose you are running the Compose Rails sample, and
+    have a `compose.yaml` file in a directory called `sandbox/rails`. You can use a command like `docker compose pull` to
+    get the postgres image for the db service from anywhere by using the `-f` flag as follows:
 
-  ```console
-  $ docker compose -f ~/sandbox/rails/compose.yaml pull db
-  ```
+    ```console
+    $ docker compose -f ~/sandbox/rails/compose.yaml pull db
+    ```
 
-  ### Use `-p` to specify a project name
+    ### Use `-p` to specify a project name
 
-  Each configuration has a project name. If you supply a `-p` flag, you can specify a project name. If you don’t
-  specify the flag, Compose uses the current directory name.
-  Project name can also be set by `COMPOSE_PROJECT_NAME` environment variable.
+    Each configuration has a project name. If you supply a `-p` flag, you can specify a project name. If you don’t
+    specify the flag, Compose uses the current directory name.
+    Project name can also be set by `COMPOSE_PROJECT_NAME` environment variable.
 
-  Most compose subcommand can be ran without a compose file, just passing
-  project name to retrieve the relevant resources.
+    Most compose subcommand can be ran without a compose file, just passing
+    project name to retrieve the relevant resources.
 
-  ```console
-  $ docker compose -p my_project ps -a
-  NAME                 SERVICE    STATUS     PORTS
-  my_project_demo_1    demo       running
+    ```console
+    $ docker compose -p my_project ps -a
+    NAME                 SERVICE    STATUS     PORTS
+    my_project_demo_1    demo       running
 
-  $ docker compose -p my_project logs
-  demo_1  | PING localhost (127.0.0.1): 56 data bytes
-  demo_1  | 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.095 ms
-  ```
+    $ docker compose -p my_project logs
+    demo_1  | PING localhost (127.0.0.1): 56 data bytes
+    demo_1  | 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.095 ms
+    ```
 
-  ### Use profiles to enable optional services
+    ### Use profiles to enable optional services
 
-  Use `--profile` to specify one or more active profiles
-  Calling `docker compose --profile frontend up` will start the services with the profile `frontend` and services
-  without any specified profiles.
-  You can also enable multiple profiles, e.g. with `docker compose --profile frontend --profile debug up` the profiles `frontend` and `debug` will be enabled.
+    Use `--profile` to specify one or more active profiles
+    Calling `docker compose --profile frontend up` will start the services with the profile `frontend` and services
+    without any specified profiles.
+    You can also enable multiple profiles, e.g. with `docker compose --profile frontend --profile debug up` the profiles `frontend` and `debug` will be enabled.
 
-  Profiles can also be set by `COMPOSE_PROFILES` environment variable.
+    Profiles can also be set by `COMPOSE_PROFILES` environment variable.
 
-  ### Set up environment variables
+    ### Set up environment variables
 
-  You can set environment variables for various docker compose options, including the `-f`, `-p` and `--profiles` flags.
+    You can set environment variables for various docker compose options, including the `-f`, `-p` and `--profiles` flags.
 
-  Setting the `COMPOSE_FILE` environment variable is equivalent to passing the `-f` flag,
-  `COMPOSE_PROJECT_NAME` environment variable does the same for to the `-p` flag,
-  and so does `COMPOSE_PROFILES` environment variable for to the `--profiles` flag.
+    Setting the `COMPOSE_FILE` environment variable is equivalent to passing the `-f` flag,
+    `COMPOSE_PROJECT_NAME` environment variable does the same for to the `-p` flag,
+    and so does `COMPOSE_PROFILES` environment variable for to the `--profiles` flag.
 
-  If flags are explicitly set on command line, associated environment variable is ignored
+    If flags are explicitly set on command line, associated environment variable is ignored
 
-  Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
-  containers for the project.
+    Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` will stop docker compose from detecting orphaned
+    containers for the project.
 usage: docker compose
 pname: docker
 plink: docker.yaml
 cname:
-- docker compose build
-- docker compose convert
-- docker compose cp
-- docker compose create
-- docker compose down
-- docker compose events
-- docker compose exec
-- docker compose images
-- docker compose kill
-- docker compose logs
-- docker compose ls
-- docker compose pause
-- docker compose port
-- docker compose ps
-- docker compose pull
-- docker compose push
-- docker compose restart
-- docker compose rm
-- docker compose run
-- docker compose start
-- docker compose stop
-- docker compose top
-- docker compose unpause
-- docker compose up
-- docker compose version
+    - docker compose build
+    - docker compose convert
+    - docker compose cp
+    - docker compose create
+    - docker compose down
+    - docker compose events
+    - docker compose exec
+    - docker compose images
+    - docker compose kill
+    - docker compose logs
+    - docker compose ls
+    - docker compose pause
+    - docker compose port
+    - docker compose ps
+    - docker compose pull
+    - docker compose push
+    - docker compose restart
+    - docker compose rm
+    - docker compose run
+    - docker compose start
+    - docker compose stop
+    - docker compose top
+    - docker compose unpause
+    - docker compose up
+    - docker compose version
 clink:
-- docker_compose_build.yaml
-- docker_compose_convert.yaml
-- docker_compose_cp.yaml
-- docker_compose_create.yaml
-- docker_compose_down.yaml
-- docker_compose_events.yaml
-- docker_compose_exec.yaml
-- docker_compose_images.yaml
-- docker_compose_kill.yaml
-- docker_compose_logs.yaml
-- docker_compose_ls.yaml
-- docker_compose_pause.yaml
-- docker_compose_port.yaml
-- docker_compose_ps.yaml
-- docker_compose_pull.yaml
-- docker_compose_push.yaml
-- docker_compose_restart.yaml
-- docker_compose_rm.yaml
-- docker_compose_run.yaml
-- docker_compose_start.yaml
-- docker_compose_stop.yaml
-- docker_compose_top.yaml
-- docker_compose_unpause.yaml
-- docker_compose_up.yaml
-- docker_compose_version.yaml
+    - docker_compose_build.yaml
+    - docker_compose_convert.yaml
+    - docker_compose_cp.yaml
+    - docker_compose_create.yaml
+    - docker_compose_down.yaml
+    - docker_compose_events.yaml
+    - docker_compose_exec.yaml
+    - docker_compose_images.yaml
+    - docker_compose_kill.yaml
+    - docker_compose_logs.yaml
+    - docker_compose_ls.yaml
+    - docker_compose_pause.yaml
+    - docker_compose_port.yaml
+    - docker_compose_ps.yaml
+    - docker_compose_pull.yaml
+    - docker_compose_push.yaml
+    - docker_compose_restart.yaml
+    - docker_compose_rm.yaml
+    - docker_compose_run.yaml
+    - docker_compose_start.yaml
+    - docker_compose_stop.yaml
+    - docker_compose_top.yaml
+    - docker_compose_unpause.yaml
+    - docker_compose_up.yaml
+    - docker_compose_version.yaml
 options:
-- option: ansi
-  value_type: string
-  default_value: auto
-  description: |
-    Control when to print ANSI control characters ("never"|"always"|"auto")
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: compatibility
-  value_type: bool
-  default_value: "false"
-  description: Run compose in backward compatibility mode
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: env-file
-  value_type: string
-  description: Specify an alternate environment file.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: file
-  shorthand: f
-  value_type: stringArray
-  default_value: '[]'
-  description: Compose configuration files
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-ansi
-  value_type: bool
-  default_value: "false"
-  description: Do not print ANSI control characters (DEPRECATED)
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: profile
-  value_type: stringArray
-  default_value: '[]'
-  description: Specify a profile to enable
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: project-directory
-  value_type: string
-  description: |-
-    Specify an alternate working directory
-    (default: the path of the, first specified, Compose file)
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: project-name
-  shorthand: p
-  value_type: string
-  description: Project name
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: verbose
-  value_type: bool
-  default_value: "false"
-  description: Show more output
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: version
-  shorthand: v
-  value_type: bool
-  default_value: "false"
-  description: Show the Docker Compose version information
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: workdir
-  value_type: string
-  description: |-
-    DEPRECATED! USE --project-directory INSTEAD.
-    Specify an alternate working directory
-    (default: the path of the, first specified, Compose file)
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: ansi
+      value_type: string
+      default_value: auto
+      description: |
+        Control when to print ANSI control characters ("never"|"always"|"auto")
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: compatibility
+      value_type: bool
+      default_value: "false"
+      description: Run compose in backward compatibility mode
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: env-file
+      value_type: string
+      description: Specify an alternate environment file.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: file
+      shorthand: f
+      value_type: stringArray
+      default_value: '[]'
+      description: Compose configuration files
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-ansi
+      value_type: bool
+      default_value: "false"
+      description: Do not print ANSI control characters (DEPRECATED)
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: profile
+      value_type: stringArray
+      default_value: '[]'
+      description: Specify a profile to enable
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: project-directory
+      value_type: string
+      description: |-
+        Specify an alternate working directory
+        (default: the path of the, first specified, Compose file)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: project-name
+      shorthand: p
+      value_type: string
+      description: Project name
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: verbose
+      value_type: bool
+      default_value: "false"
+      description: Show more output
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: version
+      shorthand: v
+      value_type: bool
+      default_value: "false"
+      description: Show the Docker Compose version information
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: workdir
+      value_type: string
+      description: |-
+        DEPRECATED! USE --project-directory INSTEAD.
+        Specify an alternate working directory
+        (default: the path of the, first specified, Compose file)
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 121 - 121
docs/reference/docker_compose_build.yaml

@@ -1,132 +1,132 @@
 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,
-  the image is tagged with that name, substituting any variables beforehand. See
-  [variable interpolation](https://github.com/compose-spec/compose-spec/blob/master/spec.md#interpolation).
+    If the Compose file specifies an
+    [image](https://github.com/compose-spec/compose-spec/blob/master/spec.md#image) name,
+    the image is tagged with that name, substituting any variables beforehand. See
+    [variable interpolation](https://github.com/compose-spec/compose-spec/blob/master/spec.md#interpolation).
 
-  If you change a service's `Dockerfile` or the contents of its build directory,
-  run `docker compose build` to rebuild it.
-usage: docker compose build [SERVICE...]
+    If you change a service's `Dockerfile` or the contents of its build directory,
+    run `docker compose build` to rebuild it.
+usage: docker compose build [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: build-arg
-  value_type: stringArray
-  default_value: '[]'
-  description: Set build-time variables for services.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: compress
-  value_type: bool
-  default_value: "true"
-  description: Compress the build context using gzip. DEPRECATED
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: force-rm
-  value_type: bool
-  default_value: "true"
-  description: Always remove intermediate containers. DEPRECATED
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: memory
-  shorthand: m
-  value_type: string
-  description: |
-    Set memory limit for the build container. Not supported on buildkit yet.
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-cache
-  value_type: bool
-  default_value: "false"
-  description: Do not use cache when building the image
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-rm
-  value_type: bool
-  default_value: "false"
-  description: |
-    Do not remove intermediate containers after a successful build. DEPRECATED
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: parallel
-  value_type: bool
-  default_value: "true"
-  description: Build images in parallel. DEPRECATED
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: progress
-  value_type: string
-  default_value: auto
-  description: Set type of progress output (auto, tty, plain, quiet)
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: pull
-  value_type: bool
-  default_value: "false"
-  description: Always attempt to pull a newer version of the image.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: quiet
-  shorthand: q
-  value_type: bool
-  default_value: "false"
-  description: Don't print anything to STDOUT
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: ssh
-  value_type: string
-  description: |
-    Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent)
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: build-arg
+      value_type: stringArray
+      default_value: '[]'
+      description: Set build-time variables for services.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: compress
+      value_type: bool
+      default_value: "true"
+      description: Compress the build context using gzip. DEPRECATED
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: force-rm
+      value_type: bool
+      default_value: "true"
+      description: Always remove intermediate containers. DEPRECATED
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: memory
+      shorthand: m
+      value_type: string
+      description: |
+        Set memory limit for the build container. Not supported on buildkit yet.
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-cache
+      value_type: bool
+      default_value: "false"
+      description: Do not use cache when building the image
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-rm
+      value_type: bool
+      default_value: "false"
+      description: |
+        Do not remove intermediate containers after a successful build. DEPRECATED
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: parallel
+      value_type: bool
+      default_value: "true"
+      description: Build images in parallel. DEPRECATED
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: progress
+      value_type: string
+      default_value: auto
+      description: Set type of progress output (auto, tty, plain, quiet)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: pull
+      value_type: bool
+      default_value: "false"
+      description: Always attempt to pull a newer version of the image.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: quiet
+      shorthand: q
+      value_type: bool
+      default_value: "false"
+      description: Don't print anything to STDOUT
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: ssh
+      value_type: string
+      description: |
+        Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 116 - 116
docs/reference/docker_compose_convert.yaml

@@ -1,126 +1,126 @@
 command: docker compose convert
-aliases: config
+aliases: docker compose convert, docker compose config
 short: Converts the compose file to platform's canonical format
 long: |-
-  `docker compose convert` render the actual data model to be applied on target platform. When used with Docker engine,
-  it merges the Compose files set by `-f` flags, resolves variables in Compose file, and expands short-notation into
-  fully defined Compose model.
+    `docker compose convert` render the actual data model to be applied on target platform. When used with Docker engine,
+    it merges the Compose files set by `-f` flags, resolves variables in Compose file, and expands short-notation into
+    fully defined Compose model.
 
-  To allow smooth migration from docker-compose, this subcommand declares alias `docker compose config`
-usage: docker compose convert SERVICES
+    To allow smooth migration from docker-compose, this subcommand declares alias `docker compose config`
+usage: docker compose convert [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: format
-  value_type: string
-  default_value: yaml
-  description: 'Format the output. Values: [yaml | json]'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: hash
-  value_type: string
-  description: Print the service config hash, one per line.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: images
-  value_type: bool
-  default_value: "false"
-  description: Print the image names, one per line.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-interpolate
-  value_type: bool
-  default_value: "false"
-  description: Don't interpolate environment variables.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-normalize
-  value_type: bool
-  default_value: "false"
-  description: Don't normalize compose model.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: output
-  shorthand: o
-  value_type: string
-  description: Save to file (default to stdout)
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: profiles
-  value_type: bool
-  default_value: "false"
-  description: Print the profile names, one per line.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: quiet
-  shorthand: q
-  value_type: bool
-  default_value: "false"
-  description: Only validate the configuration, don't print anything.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: resolve-image-digests
-  value_type: bool
-  default_value: "false"
-  description: Pin image tags to digests.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: services
-  value_type: bool
-  default_value: "false"
-  description: Print the service names, one per line.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: volumes
-  value_type: bool
-  default_value: "false"
-  description: Print the volume names, one per line.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: format
+      value_type: string
+      default_value: yaml
+      description: 'Format the output. Values: [yaml | json]'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: hash
+      value_type: string
+      description: Print the service config hash, one per line.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: images
+      value_type: bool
+      default_value: "false"
+      description: Print the image names, one per line.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-interpolate
+      value_type: bool
+      default_value: "false"
+      description: Don't interpolate environment variables.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-normalize
+      value_type: bool
+      default_value: "false"
+      description: Don't normalize compose model.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: output
+      shorthand: o
+      value_type: string
+      description: Save to file (default to stdout)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: profiles
+      value_type: bool
+      default_value: "false"
+      description: Print the profile names, one per line.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: quiet
+      shorthand: q
+      value_type: bool
+      default_value: "false"
+      description: Only validate the configuration, don't print anything.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: resolve-image-digests
+      value_type: bool
+      default_value: "false"
+      description: Pin image tags to digests.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: services
+      value_type: bool
+      default_value: "false"
+      description: Print the service names, one per line.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: volumes
+      value_type: bool
+      default_value: "false"
+      description: Print the volume names, one per line.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 46 - 45
docs/reference/docker_compose_cp.yaml

@@ -1,54 +1,55 @@
 command: docker compose cp
 short: Copy files/folders between a service container and the local filesystem
 long: Copy files/folders between a service container and the local filesystem
-usage: "docker compose cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|-\n\tdocker compose
-  cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH"
+usage: |-
+    docker compose cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|-
+    	docker compose cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: all
-  value_type: bool
-  default_value: "false"
-  description: Copy to all the containers of the service.
-  deprecated: true
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: archive
-  shorthand: a
-  value_type: bool
-  default_value: "false"
-  description: Archive mode (copy all uid/gid information)
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: follow-link
-  shorthand: L
-  value_type: bool
-  default_value: "false"
-  description: Always follow symbol link in SRC_PATH
-  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 there are multiple instances of a service .
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: all
+      value_type: bool
+      default_value: "false"
+      description: Copy to all the containers of the service.
+      deprecated: true
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: archive
+      shorthand: a
+      value_type: bool
+      default_value: "false"
+      description: Archive mode (copy all uid/gid information)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: follow-link
+      shorthand: L
+      value_type: bool
+      default_value: "false"
+      description: Always follow symbol link in SRC_PATH
+      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 there are multiple instances of a service .
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 53 - 43
docs/reference/docker_compose_create.yaml

@@ -1,52 +1,62 @@
 command: docker compose create
 short: Creates containers for a service.
 long: Creates containers for a service.
-usage: docker compose create [SERVICE...]
+usage: docker compose create [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: build
-  value_type: bool
-  default_value: "false"
-  description: Build images before starting containers.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: force-recreate
-  value_type: bool
-  default_value: "false"
-  description: |
-    Recreate containers even if their configuration and image haven't changed.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-build
-  value_type: bool
-  default_value: "false"
-  description: Don't build an image, even if it's missing.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-recreate
-  value_type: bool
-  default_value: "false"
-  description: |
-    If containers already exist, don't recreate them. Incompatible with --force-recreate.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: build
+      value_type: bool
+      default_value: "false"
+      description: Build images before starting containers.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: force-recreate
+      value_type: bool
+      default_value: "false"
+      description: |
+        Recreate containers even if their configuration and image haven't changed.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-build
+      value_type: bool
+      default_value: "false"
+      description: Don't build an image, even if it's missing.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-recreate
+      value_type: bool
+      default_value: "false"
+      description: |
+        If containers already exist, don't recreate them. Incompatible with --force-recreate.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: pull
+      value_type: string
+      default_value: missing
+      description: Pull image before running ("always"|"missing"|"never")
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 53 - 53
docs/reference/docker_compose_down.yaml

@@ -1,66 +1,66 @@
 command: docker compose down
 short: Stop and remove containers, networks
 long: |-
-  Stops containers and removes containers, networks, volumes, and images created by `up`.
+    Stops containers and removes containers, networks, volumes, and images created by `up`.
 
-  By default, the only things removed are:
+    By default, the only things removed are:
 
-  - Containers for services defined in the Compose file
-  - Networks defined in the networks section of the Compose file
-  - The default network, if one is used
+    - Containers for services defined in the Compose file
+    - Networks defined in the networks section of the Compose file
+    - The default network, if one is used
 
-  Networks and volumes defined as external are never removed.
+    Networks and volumes defined as external are never removed.
 
-  Anonymous volumes are not removed by default. However, as they don’t have a stable name, they will not be automatically
-  mounted by a subsequent `up`. For data that needs to persist between updates, use explicit paths as bind mounts or
-  named volumes.
-usage: docker compose down
+    Anonymous volumes are not removed by default. However, as they don’t have a stable name, they will not be automatically
+    mounted by a subsequent `up`. For data that needs to persist between updates, use explicit paths as bind mounts or
+    named volumes.
+usage: docker compose down [OPTIONS]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: remove-orphans
-  value_type: bool
-  default_value: "false"
-  description: Remove containers for services not defined in the Compose file.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: rmi
-  value_type: string
-  description: |
-    Remove images used by services. "local" remove only images that don't have a custom tag ("local"|"all")
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: timeout
-  shorthand: t
-  value_type: int
-  default_value: "10"
-  description: Specify a shutdown timeout in seconds
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: volumes
-  shorthand: v
-  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.
-  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.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: rmi
+      value_type: string
+      description: |
+        Remove images used by services. "local" remove only images that don't have a custom tag ("local"|"all")
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: timeout
+      shorthand: t
+      value_type: int
+      default_value: "10"
+      description: Specify a shutdown timeout in seconds
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: volumes
+      shorthand: v
+      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.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 27 - 27
docs/reference/docker_compose_events.yaml

@@ -1,39 +1,39 @@
 command: docker compose events
 short: Receive real time events from containers.
 long: |-
-  Stream container events for every container in the project.
+    Stream container events for every container in the project.
 
-  With the `--json` flag, a json object is printed one per line with the format:
+    With the `--json` flag, a json object is printed one per line with the format:
 
-  ```json
-  {
-      "time": "2015-11-20T18:01:03.615550",
-      "type": "container",
-      "action": "create",
-      "id": "213cf7...5fc39a",
-      "service": "web",
-      "attributes": {
-        "name": "application_web_1",
-        "image": "alpine:edge"
-      }
-  }
-  ```
+    ```json
+    {
+        "time": "2015-11-20T18:01:03.615550",
+        "type": "container",
+        "action": "create",
+        "id": "213cf7...5fc39a",
+        "service": "web",
+        "attributes": {
+          "name": "application_web_1",
+          "image": "alpine:edge"
+        }
+    }
+    ```
 
-  The events that can be received using this can be seen [here](/engine/reference/commandline/events/#object-types).
-usage: docker compose events [options] [--] [SERVICE...]
+    The events that can be received using this can be seen [here](/engine/reference/commandline/events/#object-types).
+usage: docker compose events [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: json
-  value_type: bool
-  default_value: "false"
-  description: Output events as a stream of json objects
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: json
+      value_type: bool
+      default_value: "false"
+      description: Output events as a stream of json objects
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 101 - 101
docs/reference/docker_compose_exec.yaml

@@ -1,111 +1,111 @@
 command: docker compose exec
 short: Execute a command in a running container.
 long: |-
-  This is the equivalent of `docker exec` targeting a Compose service.
+    This is the equivalent of `docker exec` targeting a Compose service.
 
-  With this subcommand you can run arbitrary commands in your services. Commands are by default allocating a TTY, so
-  you can use a command such as `docker compose exec web sh` to get an interactive prompt.
-usage: docker compose exec [options] [-e KEY=VAL...] [--] SERVICE COMMAND [ARGS...]
+    With this subcommand you can run arbitrary commands in your services. Commands are by default allocating a TTY, so
+    you can use a command such as `docker compose exec web sh` to get an interactive prompt.
+usage: docker compose exec [OPTIONS] SERVICE COMMAND [ARGS...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: detach
-  shorthand: d
-  value_type: bool
-  default_value: "false"
-  description: 'Detached mode: Run command in the background.'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: env
-  shorthand: e
-  value_type: stringArray
-  default_value: '[]'
-  description: Set environment variables
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: index
-  value_type: int
-  default_value: "1"
-  description: |
-    index of the container if there are multiple instances of a service [default: 1].
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: interactive
-  shorthand: i
-  value_type: bool
-  default_value: "true"
-  description: Keep STDIN open even if not attached.
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-TTY
-  shorthand: T
-  value_type: bool
-  default_value: "true"
-  description: |
-    Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: privileged
-  value_type: bool
-  default_value: "false"
-  description: Give extended privileges to the process.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: tty
-  shorthand: t
-  value_type: bool
-  default_value: "true"
-  description: Allocate a pseudo-TTY.
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: user
-  shorthand: u
-  value_type: string
-  description: Run the command as this user.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: workdir
-  shorthand: w
-  value_type: string
-  description: Path to workdir directory for this command.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: detach
+      shorthand: d
+      value_type: bool
+      default_value: "false"
+      description: 'Detached mode: Run command in the background.'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: env
+      shorthand: e
+      value_type: stringArray
+      default_value: '[]'
+      description: Set environment variables
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: index
+      value_type: int
+      default_value: "1"
+      description: |
+        index of the container if there are multiple instances of a service [default: 1].
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: interactive
+      shorthand: i
+      value_type: bool
+      default_value: "true"
+      description: Keep STDIN open even if not attached.
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-TTY
+      shorthand: T
+      value_type: bool
+      default_value: "true"
+      description: |
+        Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: privileged
+      value_type: bool
+      default_value: "false"
+      description: Give extended privileges to the process.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: tty
+      shorthand: t
+      value_type: bool
+      default_value: "true"
+      description: Allocate a pseudo-TTY.
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: user
+      shorthand: u
+      value_type: string
+      description: Run the command as this user.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: workdir
+      shorthand: w
+      value_type: string
+      description: Path to workdir directory for this command.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 12 - 12
docs/reference/docker_compose_images.yaml

@@ -1,21 +1,21 @@
 command: docker compose images
 short: List images used by the created containers
 long: List images used by the created containers
-usage: docker compose images [SERVICE...]
+usage: docker compose images [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: quiet
-  shorthand: q
-  value_type: bool
-  default_value: "false"
-  description: Only display IDs
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: quiet
+      shorthand: q
+      value_type: bool
+      default_value: "false"
+      description: Only display IDs
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 16 - 16
docs/reference/docker_compose_kill.yaml

@@ -1,26 +1,26 @@
 command: docker compose kill
 short: Force stop service containers.
 long: |-
-  Forces running containers to stop by sending a `SIGKILL` signal. Optionally the signal can be passed, for example:
+    Forces running containers to stop by sending a `SIGKILL` signal. Optionally the signal can be passed, for example:
 
-  ```console
-  $ docker-compose kill -s SIGINT
-  ```
-usage: docker compose kill [options] [SERVICE...]
+    ```console
+    $ docker-compose kill -s SIGINT
+    ```
+usage: docker compose kill [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: signal
-  shorthand: s
-  value_type: string
-  default_value: SIGKILL
-  description: SIGNAL to send to the container.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: signal
+      shorthand: s
+      value_type: string
+      default_value: SIGKILL
+      description: SIGNAL to send to the container.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 74 - 74
docs/reference/docker_compose_logs.yaml

@@ -1,83 +1,83 @@
 command: docker compose logs
 short: View output from containers
 long: Displays log output from services.
-usage: docker compose logs [SERVICE...]
+usage: docker compose logs [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: follow
-  shorthand: f
-  value_type: bool
-  default_value: "false"
-  description: Follow log output.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-color
-  value_type: bool
-  default_value: "false"
-  description: Produce monochrome output.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-log-prefix
-  value_type: bool
-  default_value: "false"
-  description: Don't print prefix in logs.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: since
-  value_type: string
-  description: |
-    Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: tail
-  value_type: string
-  default_value: all
-  description: |
-    Number of lines to show from the end of the logs for each container.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: timestamps
-  shorthand: t
-  value_type: bool
-  default_value: "false"
-  description: Show timestamps.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: until
-  value_type: string
-  description: |
-    Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: follow
+      shorthand: f
+      value_type: bool
+      default_value: "false"
+      description: Follow log output.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-color
+      value_type: bool
+      default_value: "false"
+      description: Produce monochrome output.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-log-prefix
+      value_type: bool
+      default_value: "false"
+      description: Don't print prefix in logs.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: since
+      value_type: string
+      description: |
+        Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: tail
+      value_type: string
+      default_value: all
+      description: |
+        Number of lines to show from the end of the logs for each container.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: timestamps
+      shorthand: t
+      value_type: bool
+      default_value: "false"
+      description: Show timestamps.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: until
+      value_type: string
+      description: |
+        Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 42 - 42
docs/reference/docker_compose_ls.yaml

@@ -1,51 +1,51 @@
 command: docker compose ls
 short: List running compose projects
 long: List Compose projects running on platform.
-usage: docker compose ls
+usage: docker compose ls [OPTIONS]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: all
-  shorthand: a
-  value_type: bool
-  default_value: "false"
-  description: Show all stopped Compose projects
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: filter
-  value_type: filter
-  description: Filter output based on conditions provided.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: format
-  value_type: string
-  default_value: pretty
-  description: 'Format the output. Values: [pretty | json].'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: quiet
-  shorthand: q
-  value_type: bool
-  default_value: "false"
-  description: Only display IDs.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: all
+      shorthand: a
+      value_type: bool
+      default_value: "false"
+      description: Show all stopped Compose projects
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: filter
+      value_type: filter
+      description: Filter output based on conditions provided.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: format
+      value_type: string
+      default_value: pretty
+      description: 'Format the output. Values: [pretty | json].'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: quiet
+      shorthand: q
+      value_type: bool
+      default_value: "false"
+      description: Only display IDs.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 1 - 1
docs/reference/docker_compose_pause.yaml

@@ -1,7 +1,7 @@
 command: docker compose pause
 short: Pause services
 long: |
-  Pauses running containers of a service. They can be unpaused with `docker compose unpause`.
+    Pauses running containers of a service. They can be unpaused with `docker compose unpause`.
 usage: docker compose pause [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml

+ 21 - 21
docs/reference/docker_compose_port.yaml

@@ -1,30 +1,30 @@
 command: docker compose port
 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
+usage: docker compose port [OPTIONS] SERVICE PRIVATE_PORT
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: index
-  value_type: int
-  default_value: "1"
-  description: index of the container if service has multiple replicas
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: protocol
-  value_type: string
-  default_value: tcp
-  description: tcp or udp
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: index
+      value_type: int
+      default_value: "1"
+      description: index of the container if service has multiple replicas
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: protocol
+      value_type: string
+      default_value: tcp
+      description: tcp or udp
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 146 - 146
docs/reference/docker_compose_ps.yaml

@@ -1,170 +1,170 @@
 command: docker compose ps
 short: List containers
 long: |-
-  Lists containers for a Compose project, with current status and exposed ports.
-  By default, both running and stopped containers are shown:
+    Lists containers for a Compose project, with current status and exposed ports.
+    By default, both running and stopped containers are shown:
 
-  ```console
-  $ docker compose ps
-  NAME           COMMAND                  SERVICE   STATUS       PORTS
-  example-bar-1  "/docker-entrypoint.…"   bar       exited (0)
-  example-foo-1  "/docker-entrypoint.…"   foo       running      0.0.0.0:8080->80/tcp
-  ```
-usage: docker compose ps [SERVICE...]
+    ```console
+    $ docker compose ps
+    NAME           COMMAND                  SERVICE   STATUS       PORTS
+    example-bar-1  "/docker-entrypoint.…"   bar       exited (0)
+    example-foo-1  "/docker-entrypoint.…"   foo       running      0.0.0.0:8080->80/tcp
+    ```
+usage: docker compose ps [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: all
-  shorthand: a
-  value_type: bool
-  default_value: "false"
-  description: |
-    Show all stopped containers (including those created by the run command)
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: filter
-  value_type: string
-  description: 'Filter services by a property (supported filters: status).'
-  details_url: '#filter'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: format
-  value_type: string
-  default_value: pretty
-  description: 'Format the output. Values: [pretty | json]'
-  details_url: '#format'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: quiet
-  shorthand: q
-  value_type: bool
-  default_value: "false"
-  description: Only display IDs
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: services
-  value_type: bool
-  default_value: "false"
-  description: Display services
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: status
-  value_type: stringArray
-  default_value: '[]'
-  description: |
-    Filter services by status. Values: [paused | restarting | removing | running | dead | created | exited]
-  details_url: '#status'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: all
+      shorthand: a
+      value_type: bool
+      default_value: "false"
+      description: |
+        Show all stopped containers (including those created by the run command)
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: filter
+      value_type: string
+      description: 'Filter services by a property (supported filters: status).'
+      details_url: '#filter'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: format
+      value_type: string
+      default_value: pretty
+      description: 'Format the output. Values: [pretty | json]'
+      details_url: '#format'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: quiet
+      shorthand: q
+      value_type: bool
+      default_value: "false"
+      description: Only display IDs
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: services
+      value_type: bool
+      default_value: "false"
+      description: Display services
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: status
+      value_type: stringArray
+      default_value: '[]'
+      description: |
+        Filter services by status. Values: [paused | restarting | removing | running | dead | created | exited]
+      details_url: '#status'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 examples: |-
-  ### Format the output (--format) {#format}
+    ### Format the output (--format) {#format}
 
-  By default, the `docker compose ps` command uses a table ("pretty") format to
-  show the containers. The `--format` flag allows you to specify alternative
-  presentations for the output. Currently supported options are `pretty` (default),
-  and `json`, which outputs information about the containers as a JSON array:
+    By default, the `docker compose ps` command uses a table ("pretty") format to
+    show the containers. The `--format` flag allows you to specify alternative
+    presentations for the output. Currently supported options are `pretty` (default),
+    and `json`, which outputs information about the containers as a JSON array:
 
-  ```console
-  $ docker compose ps --format json
-  [{"ID":"1553b0236cf4d2715845f053a4ee97042c4f9a2ef655731ee34f1f7940eaa41a","Name":"example-bar-1","Command":"/docker-entrypoint.sh nginx -g 'daemon off;'","Project":"example","Service":"bar","State":"exited","Health":"","ExitCode":0,"Publishers":null},{"ID":"f02a4efaabb67416e1ff127d51c4b5578634a0ad5743bd65225ff7d1909a3fa0","Name":"example-foo-1","Command":"/docker-entrypoint.sh nginx -g 'daemon off;'","Project":"example","Service":"foo","State":"running","Health":"","ExitCode":0,"Publishers":[{"URL":"0.0.0.0","TargetPort":80,"PublishedPort":8080,"Protocol":"tcp"}]}]
-  ```
+    ```console
+    $ docker compose ps --format json
+    [{"ID":"1553b0236cf4d2715845f053a4ee97042c4f9a2ef655731ee34f1f7940eaa41a","Name":"example-bar-1","Command":"/docker-entrypoint.sh nginx -g 'daemon off;'","Project":"example","Service":"bar","State":"exited","Health":"","ExitCode":0,"Publishers":null},{"ID":"f02a4efaabb67416e1ff127d51c4b5578634a0ad5743bd65225ff7d1909a3fa0","Name":"example-foo-1","Command":"/docker-entrypoint.sh nginx -g 'daemon off;'","Project":"example","Service":"foo","State":"running","Health":"","ExitCode":0,"Publishers":[{"URL":"0.0.0.0","TargetPort":80,"PublishedPort":8080,"Protocol":"tcp"}]}]
+    ```
 
-  The JSON output allows you to use the information in other tools for further
-  processing, for example, using the [`jq` utility](https://stedolan.github.io/jq/){:target="_blank" rel="noopener" class="_"}
-  to pretty-print the JSON:
+    The JSON output allows you to use the information in other tools for further
+    processing, for example, using the [`jq` utility](https://stedolan.github.io/jq/){:target="_blank" rel="noopener" class="_"}
+    to pretty-print the JSON:
 
-  ```console
-  $ docker compose ps --format json | jq .
-  [
-    {
-      "ID": "1553b0236cf4d2715845f053a4ee97042c4f9a2ef655731ee34f1f7940eaa41a",
-      "Name": "example-bar-1",
-      "Command": "/docker-entrypoint.sh nginx -g 'daemon off;'",
-      "Project": "example",
-      "Service": "bar",
-      "State": "exited",
-      "Health": "",
-      "ExitCode": 0,
-      "Publishers": null
-    },
-    {
-      "ID": "f02a4efaabb67416e1ff127d51c4b5578634a0ad5743bd65225ff7d1909a3fa0",
-      "Name": "example-foo-1",
-      "Command": "/docker-entrypoint.sh nginx -g 'daemon off;'",
-      "Project": "example",
-      "Service": "foo",
-      "State": "running",
-      "Health": "",
-      "ExitCode": 0,
-      "Publishers": [
-        {
-          "URL": "0.0.0.0",
-          "TargetPort": 80,
-          "PublishedPort": 8080,
-          "Protocol": "tcp"
-        }
-      ]
-    }
-  ]
-  ```
+    ```console
+    $ docker compose ps --format json | jq .
+    [
+      {
+        "ID": "1553b0236cf4d2715845f053a4ee97042c4f9a2ef655731ee34f1f7940eaa41a",
+        "Name": "example-bar-1",
+        "Command": "/docker-entrypoint.sh nginx -g 'daemon off;'",
+        "Project": "example",
+        "Service": "bar",
+        "State": "exited",
+        "Health": "",
+        "ExitCode": 0,
+        "Publishers": null
+      },
+      {
+        "ID": "f02a4efaabb67416e1ff127d51c4b5578634a0ad5743bd65225ff7d1909a3fa0",
+        "Name": "example-foo-1",
+        "Command": "/docker-entrypoint.sh nginx -g 'daemon off;'",
+        "Project": "example",
+        "Service": "foo",
+        "State": "running",
+        "Health": "",
+        "ExitCode": 0,
+        "Publishers": [
+          {
+            "URL": "0.0.0.0",
+            "TargetPort": 80,
+            "PublishedPort": 8080,
+            "Protocol": "tcp"
+          }
+        ]
+      }
+    ]
+    ```
 
-  ### Filter containers by status (--status) {#status}
+    ### Filter containers by status (--status) {#status}
 
-  Use the `--status` flag to filter the list of containers by status. For example,
-  to show only containers that are running, or only containers that have exited:
+    Use the `--status` flag to filter the list of containers by status. For example,
+    to show only containers that are running, or only containers that have exited:
 
-  ```console
-  $ docker compose ps --status=running
-  NAME           COMMAND                  SERVICE   STATUS       PORTS
-  example-foo-1  "/docker-entrypoint.…"   foo       running      0.0.0.0:8080->80/tcp
+    ```console
+    $ docker compose ps --status=running
+    NAME           COMMAND                  SERVICE   STATUS       PORTS
+    example-foo-1  "/docker-entrypoint.…"   foo       running      0.0.0.0:8080->80/tcp
 
-  $ docker compose ps --status=exited
-  NAME           COMMAND                  SERVICE   STATUS       PORTS
-  example-bar-1  "/docker-entrypoint.…"   bar       exited (0)
-  ```
+    $ docker compose ps --status=exited
+    NAME           COMMAND                  SERVICE   STATUS       PORTS
+    example-bar-1  "/docker-entrypoint.…"   bar       exited (0)
+    ```
 
-  ### Filter containers by status (--filter) {#filter}
+    ### Filter containers by status (--filter) {#filter}
 
-  The [`--status` flag](#status) is a convenience shorthand for the `--filter status=<status>`
-  flag. The example below is the equivalent to the example from the previous section,
-  this time using the `--filter` flag:
+    The [`--status` flag](#status) is a convenience shorthand for the `--filter status=<status>`
+    flag. The example below is the equivalent to the example from the previous section,
+    this time using the `--filter` flag:
 
-  ```console
-  $ docker compose ps --filter status=running
-  NAME           COMMAND                  SERVICE   STATUS       PORTS
-  example-foo-1  "/docker-entrypoint.…"   foo       running      0.0.0.0:8080->80/tcp
+    ```console
+    $ docker compose ps --filter status=running
+    NAME           COMMAND                  SERVICE   STATUS       PORTS
+    example-foo-1  "/docker-entrypoint.…"   foo       running      0.0.0.0:8080->80/tcp
 
-  $ docker compose ps --filter status=running
-  NAME           COMMAND                  SERVICE   STATUS       PORTS
-  example-bar-1  "/docker-entrypoint.…"   bar       exited (0)
-  ```
+    $ docker compose ps --filter status=running
+    NAME           COMMAND                  SERVICE   STATUS       PORTS
+    example-bar-1  "/docker-entrypoint.…"   bar       exited (0)
+    ```
 
-  The `docker compose ps` command currently only supports the `--filter status=<status>`
-  option, but additional filter options may be added in future.
+    The `docker compose ps` command currently only supports the `--filter status=<status>`
+    option, but additional filter options may be added in future.
 deprecated: false
 experimental: false
 experimentalcli: false

+ 91 - 91
docs/reference/docker_compose_pull.yaml

@@ -1,104 +1,104 @@
 command: docker compose pull
 short: Pull service images
 long: |-
-  Pulls an image associated with a service defined in a `compose.yaml` file, but does not start containers based on
-  those images.
-usage: docker compose pull [SERVICE...]
+    Pulls an image associated with a service defined in a `compose.yaml` file, but does not start containers based on
+    those images.
+usage: docker compose pull [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: ignore-pull-failures
-  value_type: bool
-  default_value: "false"
-  description: Pull what it can and ignores images with pull failures
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: include-deps
-  value_type: bool
-  default_value: "false"
-  description: Also pull services declared as dependencies
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-parallel
-  value_type: bool
-  default_value: "true"
-  description: DEPRECATED disable parallel pulling.
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: parallel
-  value_type: bool
-  default_value: "true"
-  description: DEPRECATED pull multiple images in parallel.
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: quiet
-  shorthand: q
-  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: ignore-pull-failures
+      value_type: bool
+      default_value: "false"
+      description: Pull what it can and ignores images with pull failures
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: include-deps
+      value_type: bool
+      default_value: "false"
+      description: Also pull services declared as dependencies
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-parallel
+      value_type: bool
+      default_value: "true"
+      description: DEPRECATED disable parallel pulling.
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: parallel
+      value_type: bool
+      default_value: "true"
+      description: DEPRECATED pull multiple images in parallel.
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: quiet
+      shorthand: q
+      value_type: bool
+      default_value: "false"
+      description: Pull without printing progress information
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 examples: |-
-  suppose you have this `compose.yaml`:
+    suppose you have this `compose.yaml`:
 
-  ```yaml
-  services:
-    db:
-      image: postgres
-    web:
-      build: .
-      command: bundle exec rails s -p 3000 -b '0.0.0.0'
-      volumes:
-        - .:/myapp
-      ports:
-        - "3000:3000"
-      depends_on:
-        - db
-  ```
+    ```yaml
+    services:
+      db:
+        image: postgres
+      web:
+        build: .
+        command: bundle exec rails s -p 3000 -b '0.0.0.0'
+        volumes:
+          - .:/myapp
+        ports:
+          - "3000:3000"
+        depends_on:
+          - db
+    ```
 
-  If you run `docker compose pull ServiceName` in the same directory as the `compose.yaml` file that defines the service,
-  Docker pulls the associated image. For example, to call the postgres image configured as the db service in our example,
-  you would run `docker compose pull db`.
+    If you run `docker compose pull ServiceName` in the same directory as the `compose.yaml` file that defines the service,
+    Docker pulls the associated image. For example, to call the postgres image configured as the db service in our example,
+    you would run `docker compose pull db`.
 
-  ```console
-  $ docker compose pull db
-  [+] Running 1/15
-   ⠸ db Pulling                                                             12.4s
-     ⠿ 45b42c59be33 Already exists                                           0.0s
-     ⠹ 40adec129f1a Downloading  3.374MB/4.178MB                             9.3s
-     ⠹ b4c431d00c78 Download complete                                        9.3s
-     ⠹ 2696974e2815 Download complete                                        9.3s
-     ⠹ 564b77596399 Downloading  5.622MB/7.965MB                             9.3s
-     ⠹ 5044045cf6f2 Downloading  216.7kB/391.1kB                             9.3s
-     ⠹ d736e67e6ac3 Waiting                                                  9.3s
-     ⠹ 390c1c9a5ae4 Waiting                                                  9.3s
-     ⠹ c0e62f172284 Waiting                                                  9.3s
-     ⠹ ebcdc659c5bf Waiting                                                  9.3s
-     ⠹ 29be22cb3acc Waiting                                                  9.3s
-     ⠹ f63c47038e66 Waiting                                                  9.3s
-     ⠹ 77a0c198cde5 Waiting                                                  9.3s
-     ⠹ c8752d5b785c Waiting                                                  9.3s
-  ``̀`
+    ```console
+    $ docker compose pull db
+    [+] Running 1/15
+     ⠸ db Pulling                                                             12.4s
+       ⠿ 45b42c59be33 Already exists                                           0.0s
+       ⠹ 40adec129f1a Downloading  3.374MB/4.178MB                             9.3s
+       ⠹ b4c431d00c78 Download complete                                        9.3s
+       ⠹ 2696974e2815 Download complete                                        9.3s
+       ⠹ 564b77596399 Downloading  5.622MB/7.965MB                             9.3s
+       ⠹ 5044045cf6f2 Downloading  216.7kB/391.1kB                             9.3s
+       ⠹ d736e67e6ac3 Waiting                                                  9.3s
+       ⠹ 390c1c9a5ae4 Waiting                                                  9.3s
+       ⠹ c0e62f172284 Waiting                                                  9.3s
+       ⠹ ebcdc659c5bf Waiting                                                  9.3s
+       ⠹ 29be22cb3acc Waiting                                                  9.3s
+       ⠹ f63c47038e66 Waiting                                                  9.3s
+       ⠹ 77a0c198cde5 Waiting                                                  9.3s
+       ⠹ c8752d5b785c Waiting                                                  9.3s
+    ```
 deprecated: false
 experimental: false
 experimentalcli: false

+ 25 - 25
docs/reference/docker_compose_push.yaml

@@ -1,38 +1,38 @@
 command: docker compose push
 short: Push service images
 long: |-
-  Pushes images for services to their respective registry/repository.
+    Pushes images for services to their respective registry/repository.
 
-  The following assumptions are made:
-  - You are pushing an image you have built locally
-  - You have access to the build key
+    The following assumptions are made:
+    - You are pushing an image you have built locally
+    - You have access to the build key
 
-  Examples
+    Examples
 
-  ```yaml
-  services:
-    service1:
-      build: .
-      image: localhost:5000/yourimage  ## goes to local registry
+    ```yaml
+    services:
+      service1:
+        build: .
+        image: localhost:5000/yourimage  ## goes to local registry
 
-    service2:
-      build: .
-      image: your-dockerid/yourimage  ## goes to your repository on Docker Hub
-  ```
-usage: docker compose push [SERVICE...]
+      service2:
+        build: .
+        image: your-dockerid/yourimage  ## goes to your repository on Docker Hub
+    ```
+usage: docker compose push [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: ignore-push-failures
-  value_type: bool
-  default_value: "false"
-  description: Push what it can and ignores images with push failures
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: ignore-push-failures
+      value_type: bool
+      default_value: "false"
+      description: Push what it can and ignores images with push failures
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 21 - 21
docs/reference/docker_compose_restart.yaml

@@ -1,31 +1,31 @@
 command: docker compose restart
-short: Restart containers
+short: Restart service containers
 long: |-
-  Restarts all stopped and running services.
+    Restarts all stopped and running services, or the specified services only.
 
-  If you make changes to your `compose.yml` configuration, these changes are not reflected
-  after running this command. For example, changes to environment variables (which are added
-  after a container is built, but before the container's command is executed) are not updated
-  after restarting.
+    If you make changes to your `compose.yml` configuration, these changes are not reflected
+    after running this command. For example, changes to environment variables (which are added
+    after a container is built, but before the container's command is executed) are not updated
+    after restarting.
 
-  If you are looking to configure a service's restart policy, please refer to
-  [restart](https://github.com/compose-spec/compose-spec/blob/master/spec.md#restart)
-  or [restart_policy](https://github.com/compose-spec/compose-spec/blob/master/deploy.md#restart_policy).
-usage: docker compose restart
+    If you are looking to configure a service's restart policy, please refer to
+    [restart](https://github.com/compose-spec/compose-spec/blob/master/spec.md#restart)
+    or [restart_policy](https://github.com/compose-spec/compose-spec/blob/master/deploy.md#restart_policy).
+usage: docker compose restart [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: timeout
-  shorthand: t
-  value_type: int
-  default_value: "10"
-  description: Specify a shutdown timeout in seconds
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: timeout
+      shorthand: t
+      value_type: int
+      default_value: "10"
+      description: Specify a shutdown timeout in seconds
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 56 - 56
docs/reference/docker_compose_rm.yaml

@@ -1,69 +1,69 @@
 command: docker compose rm
 short: Removes stopped service containers
 long: |-
-  Removes stopped service containers.
+    Removes stopped service containers.
 
-  By default, anonymous volumes attached to containers are not removed. You can override this with `-v`. To list all
-  volumes, use `docker volume ls`.
+    By default, anonymous volumes attached to containers are not removed. You can override this with `-v`. To list all
+    volumes, use `docker volume ls`.
 
-  Any data which is not in a volume is lost.
+    Any data which is not in a volume is lost.
 
-  Running the command with no options also removes one-off containers created by `docker compose run`:
+    Running the command with no options also removes one-off containers created by `docker compose run`:
 
-  ```console
-  $ docker compose rm
-  Going to remove djangoquickstart_web_run_1
-  Are you sure? [yN] y
-  Removing djangoquickstart_web_run_1 ... done
-  ```
-usage: docker compose rm [SERVICE...]
+    ```console
+    $ docker compose rm
+    Going to remove djangoquickstart_web_run_1
+    Are you sure? [yN] y
+    Removing djangoquickstart_web_run_1 ... done
+    ```
+usage: docker compose rm [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: all
-  shorthand: a
-  value_type: bool
-  default_value: "false"
-  description: Deprecated - no effect
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: force
-  shorthand: f
-  value_type: bool
-  default_value: "false"
-  description: Don't ask to confirm removal
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: stop
-  shorthand: s
-  value_type: bool
-  default_value: "false"
-  description: Stop the containers, if required, before removing
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: volumes
-  shorthand: v
-  value_type: bool
-  default_value: "false"
-  description: Remove any anonymous volumes attached to containers
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: all
+      shorthand: a
+      value_type: bool
+      default_value: "false"
+      description: Deprecated - no effect
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: force
+      shorthand: f
+      value_type: bool
+      default_value: "false"
+      description: Don't ask to confirm removal
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: stop
+      shorthand: s
+      value_type: bool
+      default_value: "false"
+      description: Stop the containers, if required, before removing
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: volumes
+      shorthand: v
+      value_type: bool
+      default_value: "false"
+      description: Remove any anonymous volumes attached to containers
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 216 - 217
docs/reference/docker_compose_run.yaml

@@ -1,242 +1,241 @@
 command: docker compose run
 short: Run a one-off command on a service.
 long: |-
-  Runs a one-time command against a service.
+    Runs a one-time command against a service.
 
-  the following command starts the `web` service and runs `bash` as its command:
+    the following command starts the `web` service and runs `bash` as its command:
 
-  ```console
-  $ docker compose run web bash
-  ```
+    ```console
+    $ docker compose run web bash
+    ```
 
-  Commands you use with run start in new containers with configuration defined by that of the service,
-  including volumes, links, and other details. However, there are two important differences:
+    Commands you use with run start in new containers with configuration defined by that of the service,
+    including volumes, links, and other details. However, there are two important differences:
 
-  First, the command passed by `run` overrides the command defined in the service configuration. For example, if the
-  `web` service configuration is started with `bash`, then `docker compose run web python app.py` overrides it with
-  `python app.py`.
+    First, the command passed by `run` overrides the command defined in the service configuration. For example, if the
+    `web` service configuration is started with `bash`, then `docker compose run web python app.py` overrides it with
+    `python app.py`.
 
-  The second difference is that the `docker compose run` command does not create any of the ports specified in the
-  service configuration. This prevents port collisions with already-open ports. If you do want the service’s ports
-  to be created and mapped to the host, specify the `--service-ports`
+    The second difference is that the `docker compose run` command does not create any of the ports specified in the
+    service configuration. This prevents port collisions with already-open ports. If you do want the service’s ports
+    to be created and mapped to the host, specify the `--service-ports`
 
-  ```console
-  $ docker compose run --service-ports web python manage.py shell
-  ```
+    ```console
+    $ docker compose run --service-ports web python manage.py shell
+    ```
 
-  Alternatively, manual port mapping can be specified with the `--publish` or `-p` options, just as when using docker run:
+    Alternatively, manual port mapping can be specified with the `--publish` or `-p` options, just as when using docker run:
 
-  ```console
-  $ docker compose run --publish 8080:80 -p 2022:22 -p 127.0.0.1:2021:21 web python manage.py shell
-  ```
+    ```console
+    $ docker compose run --publish 8080:80 -p 2022:22 -p 127.0.0.1:2021:21 web python manage.py shell
+    ```
 
-  If you start a service configured with links, the run command first checks to see if the linked service is running
-  and starts the service if it is stopped. Once all the linked services are running, the run executes the command you
-  passed it. For example, you could run:
+    If you start a service configured with links, the run command first checks to see if the linked service is running
+    and starts the service if it is stopped. Once all the linked services are running, the run executes the command you
+    passed it. For example, you could run:
 
-  ```console
-  $ docker compose run db psql -h db -U docker
-  ```
+    ```console
+    $ docker compose run db psql -h db -U docker
+    ```
 
-  This opens an interactive PostgreSQL shell for the linked `db` container.
+    This opens an interactive PostgreSQL shell for the linked `db` container.
 
-  If you do not want the run command to start linked containers, use the `--no-deps` flag:
+    If you do not want the run command to start linked containers, use the `--no-deps` flag:
 
-  ```console
-  $ docker compose run --no-deps web python manage.py shell
-  ```
+    ```console
+    $ docker compose run --no-deps web python manage.py shell
+    ```
 
-  If you want to remove the container after running while overriding the container’s restart policy, use the `--rm` flag:
+    If you want to remove the container after running while overriding the container’s restart policy, use the `--rm` flag:
 
-  ```console
-  $ docker compose run --rm web python manage.py db upgrade
-  ```
+    ```console
+    $ docker compose run --rm web python manage.py db upgrade
+    ```
 
-  This runs a database upgrade script, and removes the container when finished running, even if a restart policy is
-  specified in the service configuration.
-usage: docker compose run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l
-  KEY=VALUE...] SERVICE [COMMAND] [ARGS...]
+    This runs a database upgrade script, and removes the container when finished running, even if a restart policy is
+    specified in the service configuration.
+usage: docker compose run [OPTIONS] SERVICE [COMMAND] [ARGS...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: detach
-  shorthand: d
-  value_type: bool
-  default_value: "false"
-  description: Run container in background and print container ID
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: entrypoint
-  value_type: string
-  description: Override the entrypoint of the image
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: env
-  shorthand: e
-  value_type: stringArray
-  default_value: '[]'
-  description: Set environment variables
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: interactive
-  shorthand: i
-  value_type: bool
-  default_value: "true"
-  description: Keep STDIN open even if not attached.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: label
-  shorthand: l
-  value_type: stringArray
-  default_value: '[]'
-  description: Add or override a label
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: name
-  value_type: string
-  description: Assign a name to the container
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-TTY
-  shorthand: T
-  value_type: bool
-  default_value: "true"
-  description: 'Disable pseudo-TTY allocation (default: auto-detected).'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-deps
-  value_type: bool
-  default_value: "false"
-  description: Don't start linked services.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: publish
-  shorthand: p
-  value_type: stringArray
-  default_value: '[]'
-  description: Publish a container's port(s) to the host.
-  deprecated: false
-  hidden: false
-  experimental: false
-  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: rm
-  value_type: bool
-  default_value: "false"
-  description: Automatically remove the container when it exits
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: service-ports
-  value_type: bool
-  default_value: "false"
-  description: |
-    Run command with the service's ports enabled and mapped to the host.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: tty
-  shorthand: t
-  value_type: bool
-  default_value: "true"
-  description: Allocate a pseudo-TTY.
-  deprecated: false
-  hidden: true
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: use-aliases
-  value_type: bool
-  default_value: "false"
-  description: |
-    Use the service's network useAliases in the network(s) the container connects to.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: user
-  shorthand: u
-  value_type: string
-  description: Run as specified username or uid
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: volume
-  shorthand: v
-  value_type: stringArray
-  default_value: '[]'
-  description: Bind mount a volume.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: workdir
-  shorthand: w
-  value_type: string
-  description: Working directory inside the container
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: detach
+      shorthand: d
+      value_type: bool
+      default_value: "false"
+      description: Run container in background and print container ID
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: entrypoint
+      value_type: string
+      description: Override the entrypoint of the image
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: env
+      shorthand: e
+      value_type: stringArray
+      default_value: '[]'
+      description: Set environment variables
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: interactive
+      shorthand: i
+      value_type: bool
+      default_value: "true"
+      description: Keep STDIN open even if not attached.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: label
+      shorthand: l
+      value_type: stringArray
+      default_value: '[]'
+      description: Add or override a label
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: name
+      value_type: string
+      description: Assign a name to the container
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-TTY
+      shorthand: T
+      value_type: bool
+      default_value: "true"
+      description: 'Disable pseudo-TTY allocation (default: auto-detected).'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-deps
+      value_type: bool
+      default_value: "false"
+      description: Don't start linked services.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: publish
+      shorthand: p
+      value_type: stringArray
+      default_value: '[]'
+      description: Publish a container's port(s) to the host.
+      deprecated: false
+      hidden: false
+      experimental: false
+      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: rm
+      value_type: bool
+      default_value: "false"
+      description: Automatically remove the container when it exits
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: service-ports
+      value_type: bool
+      default_value: "false"
+      description: |
+        Run command with the service's ports enabled and mapped to the host.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: tty
+      shorthand: t
+      value_type: bool
+      default_value: "true"
+      description: Allocate a pseudo-TTY.
+      deprecated: false
+      hidden: true
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: use-aliases
+      value_type: bool
+      default_value: "false"
+      description: |
+        Use the service's network useAliases in the network(s) the container connects to.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: user
+      shorthand: u
+      value_type: string
+      description: Run as specified username or uid
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: volume
+      shorthand: v
+      value_type: stringArray
+      default_value: '[]'
+      description: Bind mount a volume.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: workdir
+      shorthand: w
+      value_type: string
+      description: Working directory inside the container
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 13 - 13
docs/reference/docker_compose_stop.yaml

@@ -1,22 +1,22 @@
 command: docker compose stop
 short: Stop services
 long: |
-  Stops running containers without removing them. They can be started again with `docker compose start`.
-usage: docker compose stop [SERVICE...]
+    Stops running containers without removing them. They can be started again with `docker compose start`.
+usage: docker compose stop [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: timeout
-  shorthand: t
-  value_type: int
-  default_value: "10"
-  description: Specify a shutdown timeout in seconds
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: timeout
+      shorthand: t
+      value_type: int
+      default_value: "10"
+      description: Specify a shutdown timeout in seconds
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 6 - 6
docs/reference/docker_compose_top.yaml

@@ -5,12 +5,12 @@ usage: docker compose top [SERVICES...]
 pname: docker compose
 plink: docker_compose.yaml
 examples: |-
-  ```console
-  $ docker compose top
-  example_foo_1
-  UID    PID      PPID     C    STIME   TTY   TIME       CMD
-  root   142353   142331   2    15:33   ?     00:00:00   ping localhost -c 5
-  ```
+    ```console
+    $ docker compose top
+    example_foo_1
+    UID    PID      PPID     C    STIME   TTY   TIME       CMD
+    root   142353   142331   2    15:33   ?     00:00:00   ping localhost -c 5
+    ```
 deprecated: false
 experimental: false
 experimentalcli: false

+ 231 - 221
docs/reference/docker_compose_up.yaml

@@ -1,235 +1,245 @@
 command: docker compose up
 short: Create and start containers
 long: |-
-  Builds, (re)creates, starts, and attaches to containers for a service.
+    Builds, (re)creates, starts, and attaches to containers for a service.
 
-  Unless they are already running, this command also starts any linked services.
+    Unless they are already running, this command also starts any linked services.
 
-  The `docker compose up` command aggregates the output of each container (like `docker compose logs --follow` does).
-  When the command exits, all containers are stopped. Running `docker compose up --detach` starts the containers in the
-  background and leaves them running.
+    The `docker compose up` command aggregates the output of each container (like `docker compose logs --follow` does).
+    When the command exits, all containers are stopped. Running `docker compose up --detach` starts the containers in the
+    background and leaves them running.
 
-  If there are existing containers for a service, and the service’s configuration or image was changed after the
-  container’s creation, `docker compose up` picks up the changes by stopping and recreating the containers
-  (preserving mounted volumes). To prevent Compose from picking up changes, use the `--no-recreate` flag.
+    If there are existing containers for a service, and the service’s configuration or image was changed after the
+    container’s creation, `docker compose up` picks up the changes by stopping and recreating the containers
+    (preserving mounted volumes). To prevent Compose from picking up changes, use the `--no-recreate` flag.
 
-  If you want to force Compose to stop and recreate all containers, use the `--force-recreate` flag.
+    If you want to force Compose to stop and recreate all containers, use the `--force-recreate` flag.
 
-  If the process encounters an error, the exit code for this command is `1`.
-  If the process is interrupted using `SIGINT` (ctrl + C) or `SIGTERM`, the containers are stopped, and the exit code is `0`.
-usage: docker compose up [SERVICE...]
+    If the process encounters an error, the exit code for this command is `1`.
+    If the process is interrupted using `SIGINT` (ctrl + C) or `SIGTERM`, the containers are stopped, and the exit code is `0`.
+usage: docker compose up [OPTIONS] [SERVICE...]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: abort-on-container-exit
-  value_type: bool
-  default_value: "false"
-  description: |
-    Stops all containers if any container was stopped. Incompatible with -d
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: always-recreate-deps
-  value_type: bool
-  default_value: "false"
-  description: Recreate dependent containers. Incompatible with --no-recreate.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: attach
-  value_type: stringArray
-  default_value: '[]'
-  description: Attach to service output.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: attach-dependencies
-  value_type: bool
-  default_value: "false"
-  description: Attach to dependent containers.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: build
-  value_type: bool
-  default_value: "false"
-  description: Build images before starting containers.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: detach
-  shorthand: d
-  value_type: bool
-  default_value: "false"
-  description: 'Detached mode: Run containers in the background'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: exit-code-from
-  value_type: string
-  description: |
-    Return the exit code of the selected service container. Implies --abort-on-container-exit
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: force-recreate
-  value_type: bool
-  default_value: "false"
-  description: |
-    Recreate containers even if their configuration and image haven't changed.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-build
-  value_type: bool
-  default_value: "false"
-  description: Don't build an image, even if it's missing.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-color
-  value_type: bool
-  default_value: "false"
-  description: Produce monochrome output.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-deps
-  value_type: bool
-  default_value: "false"
-  description: Don't start linked services.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-log-prefix
-  value_type: bool
-  default_value: "false"
-  description: Don't print prefix in logs.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-recreate
-  value_type: bool
-  default_value: "false"
-  description: |
-    If containers already exist, don't recreate them. Incompatible with --force-recreate.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: no-start
-  value_type: bool
-  default_value: "false"
-  description: Don't start the services after creating them.
-  deprecated: false
-  hidden: false
-  experimental: false
-  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.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: renew-anon-volumes
-  shorthand: V
-  value_type: bool
-  default_value: "false"
-  description: |
-    Recreate anonymous volumes instead of retrieving data from the previous containers.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: scale
-  value_type: stringArray
-  default_value: '[]'
-  description: |
-    Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: timeout
-  shorthand: t
-  value_type: int
-  default_value: "10"
-  description: |
-    Use this timeout in seconds for container shutdown when attached or when containers are already running.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: wait
-  value_type: bool
-  default_value: "false"
-  description: Wait for services to be running|healthy. Implies detached mode.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: abort-on-container-exit
+      value_type: bool
+      default_value: "false"
+      description: |
+        Stops all containers if any container was stopped. Incompatible with -d
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: always-recreate-deps
+      value_type: bool
+      default_value: "false"
+      description: Recreate dependent containers. Incompatible with --no-recreate.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: attach
+      value_type: stringArray
+      default_value: '[]'
+      description: Attach to service output.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: attach-dependencies
+      value_type: bool
+      default_value: "false"
+      description: Attach to dependent containers.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: build
+      value_type: bool
+      default_value: "false"
+      description: Build images before starting containers.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: detach
+      shorthand: d
+      value_type: bool
+      default_value: "false"
+      description: 'Detached mode: Run containers in the background'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: exit-code-from
+      value_type: string
+      description: |
+        Return the exit code of the selected service container. Implies --abort-on-container-exit
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: force-recreate
+      value_type: bool
+      default_value: "false"
+      description: |
+        Recreate containers even if their configuration and image haven't changed.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-build
+      value_type: bool
+      default_value: "false"
+      description: Don't build an image, even if it's missing.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-color
+      value_type: bool
+      default_value: "false"
+      description: Produce monochrome output.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-deps
+      value_type: bool
+      default_value: "false"
+      description: Don't start linked services.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-log-prefix
+      value_type: bool
+      default_value: "false"
+      description: Don't print prefix in logs.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-recreate
+      value_type: bool
+      default_value: "false"
+      description: |
+        If containers already exist, don't recreate them. Incompatible with --force-recreate.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: no-start
+      value_type: bool
+      default_value: "false"
+      description: Don't start the services after creating them.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: pull
+      value_type: string
+      default_value: missing
+      description: Pull image before running ("always"|"missing"|"never")
+      deprecated: false
+      hidden: false
+      experimental: false
+      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.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: renew-anon-volumes
+      shorthand: V
+      value_type: bool
+      default_value: "false"
+      description: |
+        Recreate anonymous volumes instead of retrieving data from the previous containers.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: scale
+      value_type: stringArray
+      default_value: '[]'
+      description: |
+        Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: timeout
+      shorthand: t
+      value_type: int
+      default_value: "10"
+      description: |
+        Use this timeout in seconds for container shutdown when attached or when containers are already running.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: wait
+      value_type: bool
+      default_value: "false"
+      description: Wait for services to be running|healthy. Implies detached mode.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 21 - 21
docs/reference/docker_compose_version.yaml

@@ -1,30 +1,30 @@
 command: docker compose version
 short: Show the Docker Compose version information
 long: Show the Docker Compose version information
-usage: docker compose version
+usage: docker compose version [OPTIONS]
 pname: docker compose
 plink: docker_compose.yaml
 options:
-- option: format
-  shorthand: f
-  value_type: string
-  description: 'Format the output. Values: [pretty | json]. (Default: pretty)'
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
-- option: short
-  value_type: bool
-  default_value: "false"
-  description: Shows only Compose's version number.
-  deprecated: false
-  hidden: false
-  experimental: false
-  experimentalcli: false
-  kubernetes: false
-  swarm: false
+    - option: format
+      shorthand: f
+      value_type: string
+      description: 'Format the output. Values: [pretty | json]. (Default: pretty)'
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
+    - option: short
+      value_type: bool
+      default_value: "false"
+      description: Shows only Compose's version number.
+      deprecated: false
+      hidden: false
+      experimental: false
+      experimentalcli: false
+      kubernetes: false
+      swarm: false
 deprecated: false
 experimental: false
 experimentalcli: false

+ 12 - 13
go.mod

@@ -5,14 +5,14 @@ go 1.18
 require (
 	github.com/AlecAivazis/survey/v2 v2.3.5
 	github.com/buger/goterm v1.0.4
-	github.com/cnabio/cnab-to-oci v0.3.4
-	github.com/compose-spec/compose-go v1.2.8
+	github.com/cnabio/cnab-to-oci v0.3.6
+	github.com/compose-spec/compose-go v1.4.0
 	github.com/containerd/console v1.0.3
-	github.com/containerd/containerd v1.6.6
-	github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e
+	github.com/containerd/containerd v1.6.7
+	github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f
 	github.com/docker/buildx v0.8.2 // when updating, also update the replace rules accordingly
 	github.com/docker/cli v20.10.17+incompatible
-	github.com/docker/cli-docs-tool v0.4.0
+	github.com/docker/cli-docs-tool v0.5.0
 	github.com/docker/docker v20.10.17+incompatible
 	github.com/docker/go-connections v0.4.0
 	github.com/docker/go-units v0.4.0
@@ -21,19 +21,19 @@ require (
 	github.com/hashicorp/go-version v1.6.0
 	github.com/mattn/go-isatty v0.0.14
 	github.com/mattn/go-shellwords v1.0.12
-	github.com/moby/buildkit v0.10.1-0.20220403220257-10e6f94bf90d
+	github.com/moby/buildkit v0.10.3
 	github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
 	github.com/morikuni/aec v1.0.0
 	github.com/opencontainers/go-digest v1.0.0
 	github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
 	github.com/pkg/errors v0.9.1
-	github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b
-	github.com/sirupsen/logrus v1.8.1
+	github.com/sirupsen/logrus v1.9.0
 	github.com/spf13/cobra v1.5.0
 	github.com/spf13/pflag v1.0.5
 	github.com/stretchr/testify v1.8.0
 	github.com/theupdateframework/notary v0.7.0
-	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
+	golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
+	gopkg.in/yaml.v2 v2.4.0
 	gotest.tools v2.2.0+incompatible
 	gotest.tools/v3 v3.3.0
 )
@@ -45,7 +45,7 @@ require (
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/cnabio/cnab-go v0.23.4 // indirect
-	github.com/containerd/continuity v0.2.2 // indirect
+	github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8 // indirect
 	github.com/containerd/ttrpc v1.1.0 // indirect
 	github.com/containerd/typeurl v1.0.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // indirect
@@ -61,7 +61,7 @@ require (
 	github.com/gogo/googleapis v1.4.1 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/protobuf v1.5.2 // indirect
-	github.com/google/go-cmp v0.5.7 // indirect
+	github.com/google/go-cmp v0.5.8 // indirect
 	github.com/google/gofuzz v1.2.0 // indirect
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
 	github.com/gorilla/mux v1.8.0 // indirect
@@ -111,7 +111,7 @@ require (
 	golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
 	golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
-	golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
+	golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
 	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
@@ -120,7 +120,6 @@ require (
 	google.golang.org/grpc v1.45.0 // indirect
 	google.golang.org/protobuf v1.27.1 // indirect
 	gopkg.in/inf.v0 v0.9.1 // indirect
-	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	k8s.io/apimachinery v0.24.1 // indirect; see replace for the actual version used
 	k8s.io/client-go v0.24.1 // indirect; see replace for the actual version used

+ 24 - 20
go.sum

@@ -141,7 +141,7 @@ github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwT
 github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
 github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
 github.com/Microsoft/hcsshim v0.9.2/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
-github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo=
+github.com/Microsoft/hcsshim v0.9.4 h1:mnUj0ivWy6UzbB1uLFqKR6F+ZyiDc7j4iGgHTpO+5+I=
 github.com/Microsoft/hcsshim/test v0.0.0-20200826032352-301c83a30e7c/go.mod h1:30A5igQ91GEmhYJF8TaRP79pMBOYynRsyOByfVV0dU4=
 github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
 github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
@@ -270,8 +270,8 @@ github.com/cloudflare/cfssl v0.0.0-20181213083726-b94e044bb51e/go.mod h1:yMWuSON
 github.com/cloudflare/cfssl v1.4.1 h1:vScfU2DrIUI9VPHBVeeAQ0q5A+9yshO1Gz+3QoUQiKw=
 github.com/cnabio/cnab-go v0.23.4 h1:jplQcSnvFyQlD6swiqL3BmqRnhbnS+lc/EKdBLH9E80=
 github.com/cnabio/cnab-go v0.23.4/go.mod h1:9EmgHR51LFqQStzaC+xHPJlkD4OPsF6Ev5Y8e/YHEns=
-github.com/cnabio/cnab-to-oci v0.3.4 h1:u1AUUplhKojCMgee17QkjU27yM1tfH9fOTFvxkrEqVw=
-github.com/cnabio/cnab-to-oci v0.3.4/go.mod h1:7f86Z39HUg67wg8dZvxvFpW2pGDjK3RwbJAMJGxTXHQ=
+github.com/cnabio/cnab-to-oci v0.3.6 h1:QVvy4WjQpGyf20xbbeYtRObX+pB8cWNuvvT/e4w1DoQ=
+github.com/cnabio/cnab-to-oci v0.3.6/go.mod h1:AvVNl0Hh3VBk1zqeLdyE5S3bTQ5EsZPPF4mUUJYyy1Y=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -286,8 +286,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
 github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
 github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
 github.com/compose-spec/compose-go v1.2.1/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8=
-github.com/compose-spec/compose-go v1.2.8 h1:ImPy82xn+rJKL5xmgEyesZEfqJmrzJ1WuZSHEhxMEFI=
-github.com/compose-spec/compose-go v1.2.8/go.mod h1:813WrDd7NtOl9ZVqswlJ5iCQy3lxI3KYxKkY8EeHQ7w=
+github.com/compose-spec/compose-go v1.4.0 h1:zaYVAZ6lIByr7Jffi20AabfeUwcTrdXfH3X1R5HEm+g=
+github.com/compose-spec/compose-go v1.4.0/go.mod h1:l7RUULbFFLzlQHuxtJr7SVLyWdqEpbJEGTWCgcu6Eqw=
 github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
 github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
 github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
@@ -330,8 +330,8 @@ github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTV
 github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
 github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
 github.com/containerd/containerd v1.6.1/go.mod h1:1nJz5xCZPusx6jJU8Frfct988y0NpumIq9ODB0kLtoE=
-github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0=
-github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0=
+github.com/containerd/containerd v1.6.7 h1:IVikHEHEMZ5SXpUa80tNGNIV7fBigjp+sOcrlzAkPCc=
+github.com/containerd/containerd v1.6.7/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0=
 github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
@@ -339,8 +339,9 @@ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cE
 github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y=
 github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ=
 github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM=
-github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA=
 github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk=
+github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8 h1:yGFEcFNMhze29DxAAB33v/1OMRYF/cM9iwwgV2P0ZrE=
+github.com/containerd/continuity v0.2.3-0.20220330195504-d132b287edc8/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk=
 github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
 github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
 github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
@@ -447,15 +448,17 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
 github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
-github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e h1:n81KvOMrLZa+VWHwST7dun9f0G98X3zREHS1ztYzZKU=
 github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e/go.mod h1:xpWTC2KnJMiDLkoawhsPQcXjvwATEBcbq0xevG2YR9M=
+github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f h1:3NCYdjXycNd/Xn/iICZzmxkiDX1e1cjTHjbMAz+wRVk=
+github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f/go.mod h1:28YO/VJk9/64+sTGNuYaBjWxrXTPrj0C0XmgTIOjxX4=
 github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
 github.com/docker/buildx v0.8.2 h1:dsd3F0hhmUydFX/KFrvbK81JvlTA4T3Iy0lwDJt4PsU=
 github.com/docker/buildx v0.8.2/go.mod h1:5sMOfNwOmO2jy/MxBL4ySk2LoLIG1tQFu2EU8wbKa34=
 github.com/docker/cli v20.10.3-0.20220309205733-2b52f62e9627+incompatible h1:RWXvuBczWuSIMjI69AnkNklNNVX2gmS0X+15AttGDVk=
 github.com/docker/cli v20.10.3-0.20220309205733-2b52f62e9627+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
-github.com/docker/cli-docs-tool v0.4.0 h1:MdfKoErGEbFqIxQ8an9BsZ+YzKUGd58RBVkV+Q82GPo=
 github.com/docker/cli-docs-tool v0.4.0/go.mod h1:rgW5KKdNpLMBIuH4WQ/1RNh38nH+/Ay5jgL4P0ZMPpY=
+github.com/docker/cli-docs-tool v0.5.0 h1:EjGwI6EyB7YemHCC7R8mwXszJTbuq0T0pFuDC5bMhcE=
+github.com/docker/cli-docs-tool v0.5.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o=
 github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY=
 github.com/docker/distribution v2.6.0-rc.1.0.20180327202408-83389a148052+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
@@ -606,8 +609,8 @@ github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQq
 github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
 github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
-github.com/gofrs/uuid v3.3.0+incompatible h1:8K4tyRfvU1CYPgJsveYFQMhpFd/wXNM7iK6rR7UHz84=
 github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
+github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
 github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
 github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
 github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
@@ -704,8 +707,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
 github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE=
 github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4=
 github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
@@ -1011,14 +1015,14 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
 github.com/moby/buildkit v0.8.1/go.mod h1:/kyU1hKy/aYCuP39GZA9MaKioovHku57N6cqlKZIaiQ=
-github.com/moby/buildkit v0.10.1-0.20220403220257-10e6f94bf90d h1:6pLVBJO3V/lMegbVD5kh2QrpZwqS4ZrxEm/MyifCPaY=
 github.com/moby/buildkit v0.10.1-0.20220403220257-10e6f94bf90d/go.mod h1:WvwAZv8aRScHkqc/+X46cRC2CKMKpqcaX+pRvUTtPes=
+github.com/moby/buildkit v0.10.3 h1:/dGykD8FW+H4p++q5+KqKEo6gAkYKyBQHdawdjVwVAU=
+github.com/moby/buildkit v0.10.3/go.mod h1:jxeOuly98l9gWHai0Ojrbnczrk/rf+o9/JqNhY+UCSo=
 github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
 github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
 github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
 github.com/moby/sys/mount v0.1.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
 github.com/moby/sys/mount v0.1.1/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
-github.com/moby/sys/mount v0.3.0 h1:bXZYMmq7DBQPwHRxH/MG+u9+XF90ZOwoXpHTOznMGp0=
 github.com/moby/sys/mount v0.3.0/go.mod h1:U2Z3ur2rXPFrFmy4q6WMwWrBOAQGYtYTRVM8BIvzbwk=
 github.com/moby/sys/mountinfo v0.1.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
 github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
@@ -1218,8 +1222,6 @@ github.com/ryancurrah/gomodguard v1.1.0/go.mod h1:4O8tr7hBODaGE6VIhfJDHcwzh5GUcc
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
 github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
-github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b h1:jUK33OXuZP/l6babJtnLo1qsGvq6G9so9KMflGAm4YA=
-github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b/go.mod h1:8458kAagoME2+LN5//WxE71ysZ3B7r22fdgb7qVmXSY=
 github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
@@ -1245,8 +1247,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
 github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
 github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
@@ -1673,8 +1676,9 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1790,8 +1794,9 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
 golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@@ -1909,7 +1914,6 @@ golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
 gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=

+ 24 - 1
pkg/api/api.go

@@ -117,7 +117,7 @@ type CreateOptions struct {
 
 // StartOptions group options of the Start API
 type StartOptions struct {
-	// Project is the compose project used to define this app. Might be nil if user ran `start` just with project name
+	// Project is the compose project used to define this app. Might be nil if user ran command just with project name
 	Project *types.Project
 	// Attach to container and forward logs if not nil
 	Attach LogConsumer
@@ -133,6 +133,8 @@ type StartOptions struct {
 
 // RestartOptions group options of the Restart API
 type RestartOptions struct {
+	// Project is the compose project used to define this app. Might be nil if user ran command just with project name
+	Project *types.Project
 	// Timeout override container restart timeout
 	Timeout *time.Duration
 	// Services passed in the command line to be restarted
@@ -141,6 +143,8 @@ type RestartOptions struct {
 
 // StopOptions group options of the Stop API
 type StopOptions struct {
+	// Project is the compose project used to define this app. Might be nil if user ran command just with project name
+	Project *types.Project
 	// Timeout override container stop timeout
 	Timeout *time.Duration
 	// Services passed in the command line to be stopped
@@ -201,6 +205,8 @@ type KillOptions struct {
 
 // RemoveOptions group options of the Remove API
 type RemoveOptions struct {
+	// Project is the compose project used to define this app. Might be nil if user ran command just with project name
+	Project *types.Project
 	// DryRun just list removable resources
 	DryRun bool
 	// Volumes remove anonymous volumes
@@ -213,6 +219,8 @@ type RemoveOptions struct {
 
 // RunOptions group options of the Run API
 type RunOptions struct {
+	// Project is the compose project used to define this app. Might be nil if user ran command just with project name
+	Project           *types.Project
 	Name              string
 	Service           string
 	Command           []string
@@ -272,6 +280,7 @@ type ListOptions struct {
 
 // PsOptions group options of the Ps API
 type PsOptions struct {
+	Project  *types.Project
 	All      bool
 	Services []string
 }
@@ -377,6 +386,8 @@ type LogOptions struct {
 type PauseOptions struct {
 	// Services passed in the command line to be started
 	Services []string
+	// Project is the compose project used to define this app. Might be nil if user ran command just with project name
+	Project *types.Project
 }
 
 const (
@@ -445,3 +456,15 @@ const (
 	// UserCancel user cancelled compose up, we are stopping containers
 	UserCancel
 )
+
+// Separator is used for naming components
+var Separator = "-"
+
+// GetImageNameOrDefault computes the default image name for a service, used to tag built images
+func GetImageNameOrDefault(service types.ServiceConfig, projectName string) string {
+	imageName := service.Image
+	if imageName == "" {
+		imageName = projectName + Separator + service.Name
+	}
+	return imageName
+}

+ 1 - 1
pkg/api/errors.go

@@ -21,7 +21,7 @@ import (
 )
 
 const (
-	//ExitCodeLoginRequired exit code when command cannot execute because it requires cloud login
+	// ExitCodeLoginRequired exit code when command cannot execute because it requires cloud login
 	// This will be used by VSCode to detect when creating context if the user needs to login first
 	ExitCodeLoginRequired = 5
 )

+ 2 - 2
pkg/compose/attach.go

@@ -127,9 +127,9 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s
 	if stdout != nil {
 		go func() {
 			if tty {
-				io.Copy(stdout, streamOut) // nolint:errcheck
+				io.Copy(stdout, streamOut) //nolint:errcheck
 			} else {
-				stdcopy.StdCopy(stdout, stderr, streamOut) // nolint:errcheck
+				stdcopy.StdCopy(stdout, stderr, streamOut) //nolint:errcheck
 			}
 		}()
 	}

+ 64 - 55
pkg/compose/build.go

@@ -48,12 +48,9 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
 
 func (s *composeService) build(ctx context.Context, project *types.Project, options api.BuildOptions) error {
 	opts := map[string]build.Options{}
-	imagesToBuild := []string{}
+	var imagesToBuild []string
 
-	args := flatten(options.Args.Resolve(func(s string) (string, bool) {
-		s, ok := project.Environment[s]
-		return s, ok
-	}))
+	args := flatten(options.Args.Resolve(envResolver(project.Environment)))
 
 	services, err := project.GetServices(options.Services...)
 	if err != nil {
@@ -61,29 +58,30 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
 	}
 
 	for _, service := range services {
-		if service.Build != nil {
-			imageName := getImageName(service, project.Name)
-			imagesToBuild = append(imagesToBuild, imageName)
-			buildOptions, err := s.toBuildOptions(project, service, imageName, options.SSHs)
-			if err != nil {
-				return err
-			}
-			buildOptions.Pull = options.Pull
-			buildOptions.BuildArgs = mergeArgs(buildOptions.BuildArgs, args)
-			buildOptions.NoCache = options.NoCache
-			buildOptions.CacheFrom, err = buildflags.ParseCacheEntry(service.Build.CacheFrom)
-			if err != nil {
-				return err
-			}
+		if service.Build == nil {
+			continue
+		}
+		imageName := api.GetImageNameOrDefault(service, project.Name)
+		imagesToBuild = append(imagesToBuild, imageName)
+		buildOptions, err := s.toBuildOptions(project, service, imageName, options.SSHs)
+		if err != nil {
+			return err
+		}
+		buildOptions.Pull = options.Pull
+		buildOptions.BuildArgs = mergeArgs(buildOptions.BuildArgs, args)
+		buildOptions.NoCache = options.NoCache
+		buildOptions.CacheFrom, err = buildflags.ParseCacheEntry(service.Build.CacheFrom)
+		if err != nil {
+			return err
+		}
 
-			for _, image := range service.Build.CacheFrom {
-				buildOptions.CacheFrom = append(buildOptions.CacheFrom, bclient.CacheOptionsEntry{
-					Type:  "registry",
-					Attrs: map[string]string{"ref": image},
-				})
-			}
-			opts[imageName] = buildOptions
+		for _, image := range service.Build.CacheFrom {
+			buildOptions.CacheFrom = append(buildOptions.CacheFrom, bclient.CacheOptionsEntry{
+				Type:  "registry",
+				Attrs: map[string]string{"ref": image},
+			})
 		}
+		opts[imageName] = buildOptions
 	}
 
 	_, err = s.doBuild(ctx, project, opts, options.Progress)
@@ -134,14 +132,13 @@ func (s *composeService) ensureImagesExists(ctx context.Context, project *types.
 	}
 	// set digest as com.docker.compose.image label so we can detect outdated containers
 	for i, service := range project.Services {
-		image := getImageName(service, project.Name)
+		image := api.GetImageNameOrDefault(service, project.Name)
 		digest, ok := images[image]
 		if ok {
 			if project.Services[i].Labels == nil {
 				project.Services[i].Labels = types.Labels{}
 			}
 			project.Services[i].CustomLabels[api.ImageDigestLabel] = digest
-			project.Services[i].Image = image
 		}
 	}
 	return nil
@@ -153,7 +150,7 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
 		if service.Image == "" && service.Build == nil {
 			return nil, fmt.Errorf("invalid service %q. Must specify either image or build", service.Name)
 		}
-		imageName := getImageName(service, project.Name)
+		imageName := api.GetImageNameOrDefault(service, project.Name)
 		_, localImagePresent := images[imageName]
 
 		if service.Build != nil {
@@ -173,9 +170,9 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
 }
 
 func (s *composeService) getLocalImagesDigests(ctx context.Context, project *types.Project) (map[string]string, error) {
-	imageNames := []string{}
+	var imageNames []string
 	for _, s := range project.Services {
-		imgName := getImageName(s, project.Name)
+		imgName := api.GetImageNameOrDefault(s, project.Name)
 		if !utils.StringContains(imageNames, imgName) {
 			imageNames = append(imageNames, imgName)
 		}
@@ -189,11 +186,11 @@ func (s *composeService) getLocalImagesDigests(ctx context.Context, project *typ
 		images[name] = info.ID
 	}
 
-	for _, s := range project.Services {
-		imgName := getImageName(s, project.Name)
+	for i := range project.Services {
+		imgName := api.GetImageNameOrDefault(project.Services[i], project.Name)
 		digest, ok := images[imgName]
 		if ok {
-			s.CustomLabels[api.ImageDigestLabel] = digest
+			project.Services[i].CustomLabels.Add(api.ImageDigestLabel, digest)
 		}
 	}
 
@@ -214,10 +211,7 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
 	var tags []string
 	tags = append(tags, imageTag)
 
-	buildArgs := flatten(service.Build.Args.Resolve(func(s string) (string, bool) {
-		s, ok := project.Environment[s]
-		return s, ok
-	}))
+	buildArgs := flatten(service.Build.Args.Resolve(envResolver(project.Environment)))
 
 	var plats []specs.Platform
 	if platform, ok := project.Environment["DOCKER_DEFAULT_PLATFORM"]; ok {
@@ -256,23 +250,11 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
 	}
 
 	if len(service.Build.Secrets) > 0 {
-		var sources []secretsprovider.Source
-		for _, secret := range service.Build.Secrets {
-			config := project.Secrets[secret.Source]
-			if config.File == "" {
-				return build.Options{}, fmt.Errorf("build.secrets only supports file-based secrets: %q", secret.Source)
-			}
-			sources = append(sources, secretsprovider.Source{
-				ID:       secret.Source,
-				FilePath: config.File,
-			})
-		}
-		store, err := secretsprovider.NewStore(sources)
+		secretsProvider, err := addSecretsConfig(project, service)
 		if err != nil {
 			return build.Options{}, err
 		}
-		p := secretsprovider.NewSecretProvider(store)
-		sessionConfig = append(sessionConfig, p)
+		sessionConfig = append(sessionConfig, secretsProvider)
 	}
 
 	if len(service.Build.Tags) > 0 {
@@ -324,11 +306,11 @@ func mergeArgs(m ...types.Mapping) types.Mapping {
 	return merged
 }
 
-func dockerFilePath(context string, dockerfile string) string {
-	if urlutil.IsGitURL(context) || filepath.IsAbs(dockerfile) {
+func dockerFilePath(ctxName string, dockerfile string) string {
+	if urlutil.IsGitURL(ctxName) || filepath.IsAbs(dockerfile) {
 		return dockerfile
 	}
-	return filepath.Join(context, dockerfile)
+	return filepath.Join(ctxName, dockerfile)
 }
 
 func sshAgentProvider(sshKeys types.SSHConfig) (session.Attachable, error) {
@@ -341,3 +323,30 @@ func sshAgentProvider(sshKeys types.SSHConfig) (session.Attachable, error) {
 	}
 	return sshprovider.NewSSHAgentProvider(sshConfig)
 }
+
+func addSecretsConfig(project *types.Project, service types.ServiceConfig) (session.Attachable, error) {
+
+	var sources []secretsprovider.Source
+	for _, secret := range service.Build.Secrets {
+		config := project.Secrets[secret.Source]
+		switch {
+		case config.File != "":
+			sources = append(sources, secretsprovider.Source{
+				ID:       secret.Source,
+				FilePath: config.File,
+			})
+		case config.Environment != "":
+			sources = append(sources, secretsprovider.Source{
+				ID:  secret.Source,
+				Env: config.Environment,
+			})
+		default:
+			return nil, fmt.Errorf("build.secrets only supports environment or file-based secrets: %q", secret.Source)
+		}
+	}
+	store, err := secretsprovider.NewStore(sources)
+	if err != nil {
+		return nil, err
+	}
+	return secretsprovider.NewSecretProvider(store), nil
+}

+ 7 - 6
pkg/compose/build_classic.go

@@ -29,6 +29,7 @@ import (
 	"github.com/compose-spec/compose-go/types"
 	buildx "github.com/docker/buildx/build"
 	"github.com/docker/cli/cli/command/image/build"
+	"github.com/docker/compose/v2/pkg/api"
 	dockertypes "github.com/docker/docker/api/types"
 	"github.com/docker/docker/cli"
 	"github.com/docker/docker/pkg/archive"
@@ -45,7 +46,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
 	var nameDigests = make(map[string]string)
 	var errs error
 	err := project.WithServices(nil, func(service types.ServiceConfig) error {
-		imageName := getImageName(service, project.Name)
+		imageName := api.GetImageNameOrDefault(service, project.Name)
 		o, ok := opts[imageName]
 		if !ok {
 			return nil
@@ -64,7 +65,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
 	return nameDigests, errs
 }
 
-// nolint: gocyclo
+//nolint: gocyclo
 func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options buildx.Options) (string, error) {
 	var (
 		buildCtx      io.ReadCloser
@@ -96,7 +97,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
 			if err != nil {
 				return "", errors.Errorf("unable to open Dockerfile: %v", err)
 			}
-			defer dockerfileCtx.Close() // nolint:errcheck
+			defer dockerfileCtx.Close() //nolint:errcheck
 		}
 	case urlutil.IsGitURL(specifiedContext):
 		tempDir, relDockerfile, err = build.GetContextFromGitURL(specifiedContext, dockerfileName)
@@ -111,7 +112,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
 	}
 
 	if tempDir != "" {
-		defer os.RemoveAll(tempDir) // nolint:errcheck
+		defer os.RemoveAll(tempDir) //nolint:errcheck
 		contextDir = tempDir
 	}
 
@@ -175,7 +176,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
 	if err != nil {
 		return "", err
 	}
-	defer response.Body.Close() // nolint:errcheck
+	defer response.Body.Close() //nolint:errcheck
 
 	imageID := ""
 	aux := func(msg jsonmessage.JSONMessage) {
@@ -214,7 +215,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
 		if imageID == "" {
 			return "", errors.Errorf("Server did not provide an image ID. Cannot write %s", options.ImageIDFile)
 		}
-		if err := os.WriteFile(options.ImageIDFile, []byte(imageID), 0666); err != nil {
+		if err := os.WriteFile(options.ImageIDFile, []byte(imageID), 0o666); err != nil {
 			return "", err
 		}
 	}

+ 2 - 24
pkg/compose/compose.go

@@ -24,6 +24,8 @@ import (
 	"io"
 	"strings"
 
+	"gopkg.in/yaml.v2"
+
 	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/cli/cli/config/configfile"
@@ -33,12 +35,8 @@ import (
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/client"
 	"github.com/pkg/errors"
-	"github.com/sanathkr/go-yaml"
 )
 
-// Separator is used for naming components
-var Separator = "-"
-
 // NewComposeService create a local implementation of the compose.Service API
 func NewComposeService(dockerCli command.Cli) api.Service {
 	return &composeService{
@@ -175,26 +173,6 @@ SERVICES:
 	return project, nil
 }
 
-// actualState list resources labelled by projectName to rebuild compose project model
-func (s *composeService) actualState(ctx context.Context, projectName string, services []string) (Containers, *types.Project, error) {
-	var containers Containers
-	// don't filter containers by options.Services so projectFromName can rebuild project with all existing resources
-	containers, err := s.getContainers(ctx, projectName, oneOffInclude, true)
-	if err != nil {
-		return nil, nil, err
-	}
-
-	project, err := s.projectFromName(containers, projectName, services...)
-	if err != nil && !api.IsNotFoundError(err) {
-		return nil, nil, err
-	}
-
-	if len(services) > 0 {
-		containers = containers.filter(isService(services...))
-	}
-	return containers, project, nil
-}
-
 func (s *composeService) actualVolumes(ctx context.Context, projectName string) (types.Volumes, error) {
 	volumes, err := s.apiClient().VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
 	if err != nil {

+ 7 - 6
pkg/compose/convergence.go

@@ -261,7 +261,7 @@ func mustRecreate(expected types.ServiceConfig, actual moby.Container, policy st
 }
 
 func getContainerName(projectName string, service types.ServiceConfig, number int) string {
-	name := strings.Join([]string{projectName, service.Name, strconv.Itoa(number)}, Separator)
+	name := strings.Join([]string{projectName, service.Name, strconv.Itoa(number)}, api.Separator)
 	if service.ContainerName != "" {
 		name = service.ContainerName
 	}
@@ -553,8 +553,8 @@ func (s composeService) getLinks(ctx context.Context, projectName string, servic
 			containerName := getCanonicalContainerName(c)
 			links = append(links,
 				format(containerName, linkName),
-				format(containerName, strings.Join([]string{linkServiceName, strconv.Itoa(number)}, Separator)),
-				format(containerName, strings.Join([]string{projectName, linkServiceName, strconv.Itoa(number)}, Separator)),
+				format(containerName, linkServiceName+api.Separator+strconv.Itoa(number)),
+				format(containerName, strings.Join([]string{projectName, linkServiceName, strconv.Itoa(number)}, api.Separator)),
 			)
 		}
 	}
@@ -568,7 +568,7 @@ func (s composeService) getLinks(ctx context.Context, projectName string, servic
 			containerName := getCanonicalContainerName(c)
 			links = append(links,
 				format(containerName, service.Name),
-				format(containerName, strings.TrimPrefix(containerName, projectName+Separator)),
+				format(containerName, strings.TrimPrefix(containerName, projectName+api.Separator)),
 				format(containerName, containerName),
 			)
 		}
@@ -605,8 +605,9 @@ func (s *composeService) connectContainerToNetwork(ctx context.Context, id strin
 		ipv4Address = cfg.Ipv4Address
 		ipv6Address = cfg.Ipv6Address
 		ipam = &network.EndpointIPAMConfig{
-			IPv4Address: ipv4Address,
-			IPv6Address: ipv6Address,
+			IPv4Address:  ipv4Address,
+			IPv6Address:  ipv6Address,
+			LinkLocalIPs: cfg.LinkLocalIPs,
 		}
 	}
 	err := s.apiClient().NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{

+ 1 - 1
pkg/compose/cp.go

@@ -263,7 +263,7 @@ func (s *composeService) copyFromContainer(ctx context.Context, containerID, src
 	}
 
 	preArchive := content
-	if len(srcInfo.RebaseName) != 0 {
+	if srcInfo.RebaseName != "" {
 		_, srcBase := archive.SplitPathDirEntry(srcInfo.Path)
 		preArchive = archive.RebaseArchiveEntries(content, srcBase, srcInfo.RebaseName)
 	}

+ 23 - 19
pkg/compose/create.go

@@ -227,14 +227,6 @@ func (s *composeService) ensureProjectVolumes(ctx context.Context, project *type
 	return nil
 }
 
-func getImageName(service types.ServiceConfig, projectName string) string {
-	imageName := service.Image
-	if imageName == "" {
-		imageName = projectName + "_" + service.Name
-	}
-	return imageName
-}
-
 func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project, service types.ServiceConfig,
 	number int, inherit *moby.Container, autoRemove bool, attachStdin bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
 
@@ -279,7 +271,7 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 		AttachStderr:    true,
 		AttachStdout:    true,
 		Cmd:             runCmd,
-		Image:           getImageName(service, p.Name),
+		Image:           api.GetImageNameOrDefault(service, p.Name),
 		WorkingDir:      service.WorkingDir,
 		Entrypoint:      entrypoint,
 		NetworkDisabled: service.NetworkMode == "disabled",
@@ -314,8 +306,9 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 			ipv4Address = config.Ipv4Address
 			ipv6Address = config.Ipv6Address
 			ipam = &network.EndpointIPAMConfig{
-				IPv4Address: ipv4Address,
-				IPv6Address: ipv6Address,
+				IPv4Address:  ipv4Address,
+				IPv6Address:  ipv6Address,
+				LinkLocalIPs: config.LinkLocalIPs,
 			}
 		}
 		networkConfig = &network.NetworkingConfig{
@@ -680,7 +673,7 @@ func getVolumesFrom(project *types.Project, volumesFrom []string) ([]string, []s
 			continue
 		}
 		if spec[0] == "container" {
-			volumes = append(volumes, strings.Join(spec[1:], ":"))
+			volumes = append(volumes, vol)
 			continue
 		}
 		serviceName := spec[0]
@@ -712,7 +705,7 @@ func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Proj
 	inherit *moby.Container) (map[string]struct{}, []string, []mount.Mount, error) {
 	var mounts = []mount.Mount{}
 
-	image := getImageName(service, p.Name)
+	image := api.GetImageNameOrDefault(service, p.Name)
 	imgInspect, _, err := s.apiClient().ImageInspectWithRaw(ctx, image)
 	if err != nil {
 		return nil, nil, nil, err
@@ -727,8 +720,12 @@ func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Proj
 	binds := []string{}
 MOUNTS:
 	for _, m := range mountOptions {
+		if m.Type == mount.TypeNamedPipe {
+			mounts = append(mounts, m)
+			continue
+		}
 		volumeMounts[m.Target] = struct{}{}
-		if m.Type == mount.TypeBind || m.Type == mount.TypeNamedPipe {
+		if m.Type == mount.TypeBind {
 			// `Mount` is preferred but does not offer option to created host path if missing
 			// so `Bind` API is used here with raw volume string
 			// see https://github.com/moby/moby/issues/43483
@@ -893,7 +890,7 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 			continue
 		}
 
-		mount, err := buildMount(p, types.ServiceVolumeConfig{
+		mnt, err := buildMount(p, types.ServiceVolumeConfig{
 			Type:     types.VolumeTypeBind,
 			Source:   definedSecret.File,
 			Target:   target,
@@ -902,7 +899,7 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 		if err != nil {
 			return nil, err
 		}
-		mounts[target] = mount
+		mounts[target] = mnt
 	}
 	values := make([]mount.Mount, 0, len(mounts))
 	for _, v := range mounts {
@@ -911,8 +908,8 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 	return values, nil
 }
 
-func isUnixAbs(path string) bool {
-	return strings.HasPrefix(path, "/")
+func isUnixAbs(p string) bool {
+	return strings.HasPrefix(p, "/")
 }
 
 func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.Mount, error) {
@@ -1041,7 +1038,14 @@ func (s *composeService) ensureNetwork(ctx context.Context, n types.NetworkConfi
 	if err != nil {
 		return err
 	}
-	if len(networks) == 0 {
+	networkNotFound := true
+	for _, net := range networks {
+		if net.Name == n.Name {
+			networkNotFound = false
+			break
+		}
+	}
+	if networkNotFound {
 		if n.External.External {
 			if n.Driver == "overlay" {
 				// Swarm nodes do not register overlay networks that were

+ 29 - 9
pkg/compose/create_test.go

@@ -22,11 +22,12 @@ import (
 	"sort"
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
-	composetypes "github.com/compose-spec/compose-go/types"
 	"github.com/docker/compose/v2/pkg/api"
+
+	composetypes "github.com/compose-spec/compose-go/types"
 	moby "github.com/docker/docker/api/types"
 	mountTypes "github.com/docker/docker/api/types/mount"
+
 	"gotest.tools/v3/assert"
 )
 
@@ -45,6 +46,18 @@ func TestBuildBindMount(t *testing.T) {
 	assert.Equal(t, mount.Type, mountTypes.TypeBind)
 }
 
+func TestBuildNamedPipeMount(t *testing.T) {
+	project := composetypes.Project{}
+	volume := composetypes.ServiceVolumeConfig{
+		Type:   composetypes.VolumeTypeNamedPipe,
+		Source: "\\\\.\\pipe\\docker_engine_windows",
+		Target: "\\\\.\\pipe\\docker_engine",
+	}
+	mount, err := buildMount(project, volume)
+	assert.NilError(t, err)
+	assert.Equal(t, mount.Type, mountTypes.TypeNamedPipe)
+}
+
 func TestBuildVolumeMount(t *testing.T) {
 	project := composetypes.Project{
 		Name: "myProject",
@@ -66,17 +79,17 @@ func TestBuildVolumeMount(t *testing.T) {
 }
 
 func TestServiceImageName(t *testing.T) {
-	assert.Equal(t, getImageName(types.ServiceConfig{Image: "myImage"}, "myProject"), "myImage")
-	assert.Equal(t, getImageName(types.ServiceConfig{Name: "aService"}, "myProject"), "myProject_aService")
+	assert.Equal(t, api.GetImageNameOrDefault(composetypes.ServiceConfig{Image: "myImage"}, "myProject"), "myImage")
+	assert.Equal(t, api.GetImageNameOrDefault(composetypes.ServiceConfig{Name: "aService"}, "myProject"), "myProject-aService")
 }
 
 func TestPrepareNetworkLabels(t *testing.T) {
-	project := types.Project{
+	project := composetypes.Project{
 		Name:     "myProject",
-		Networks: types.Networks(map[string]types.NetworkConfig{"skynet": {}}),
+		Networks: composetypes.Networks(map[string]composetypes.NetworkConfig{"skynet": {}}),
 	}
 	prepareNetworks(&project)
-	assert.DeepEqual(t, project.Networks["skynet"].Labels, types.Labels(map[string]string{
+	assert.DeepEqual(t, project.Networks["skynet"].Labels, composetypes.Labels(map[string]string{
 		"com.docker.compose.network": "skynet",
 		"com.docker.compose.project": "myProject",
 		"com.docker.compose.version": api.ComposeVersion,
@@ -98,6 +111,11 @@ func TestBuildContainerMountOptions(t *testing.T) {
 						Type:   composetypes.VolumeTypeVolume,
 						Target: "/var/myvolume2",
 					},
+					{
+						Type:   composetypes.VolumeTypeNamedPipe,
+						Source: "\\\\.\\pipe\\docker_engine_windows",
+						Target: "\\\\.\\pipe\\docker_engine",
+					},
 				},
 			},
 		},
@@ -129,18 +147,20 @@ func TestBuildContainerMountOptions(t *testing.T) {
 		return mounts[i].Target < mounts[j].Target
 	})
 	assert.NilError(t, err)
-	assert.Assert(t, len(mounts) == 2)
+	assert.Assert(t, len(mounts) == 3)
 	assert.Equal(t, mounts[0].Target, "/var/myvolume1")
 	assert.Equal(t, mounts[1].Target, "/var/myvolume2")
+	assert.Equal(t, mounts[2].Target, "\\\\.\\pipe\\docker_engine")
 
 	mounts, err = buildContainerMountOptions(project, project.Services[0], moby.ImageInspect{}, inherit)
 	sort.Slice(mounts, func(i, j int) bool {
 		return mounts[i].Target < mounts[j].Target
 	})
 	assert.NilError(t, err)
-	assert.Assert(t, len(mounts) == 2)
+	assert.Assert(t, len(mounts) == 3)
 	assert.Equal(t, mounts[0].Target, "/var/myvolume1")
 	assert.Equal(t, mounts[1].Target, "/var/myvolume2")
+	assert.Equal(t, mounts[2].Target, "\\\\.\\pipe\\docker_engine")
 }
 
 func TestGetDefaultNetworkMode(t *testing.T) {

+ 14 - 9
pkg/compose/down.go

@@ -45,8 +45,11 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
 	w := progress.ContextWriter(ctx)
 	resourceToRemove := false
 
-	var containers Containers
-	containers, err := s.getContainers(ctx, projectName, oneOffInclude, true)
+	include := oneOffExclude
+	if options.RemoveOrphans {
+		include = oneOffInclude
+	}
+	containers, err := s.getContainers(ctx, projectName, include, true)
 	if err != nil {
 		return err
 	}
@@ -163,14 +166,16 @@ func (s *composeService) removeNetwork(ctx context.Context, name string, w progr
 
 	var removed int
 	for _, net := range networks {
-		if err := s.apiClient().NetworkRemove(ctx, net.ID); err != nil {
-			if errdefs.IsNotFound(err) {
-				continue
+		if net.Name == name {
+			if err := s.apiClient().NetworkRemove(ctx, net.ID); err != nil {
+				if errdefs.IsNotFound(err) {
+					continue
+				}
+				w.Event(progress.ErrorEvent(eventName))
+				return errors.Wrapf(err, fmt.Sprintf("failed to remove network %s", name))
 			}
-			w.Event(progress.ErrorEvent(eventName))
-			return errors.Wrapf(err, fmt.Sprintf("failed to remove network %s", name))
+			removed++
 		}
-		removed++
 	}
 
 	if removed == 0 {
@@ -193,7 +198,7 @@ func (s *composeService) getServiceImages(options api.DownOptions, project *type
 			continue
 		}
 		if image == "" {
-			image = getImageName(service, project.Name)
+			image = api.GetImageNameOrDefault(service, project.Name)
 		}
 		images[image] = struct{}{}
 	}

+ 3 - 3
pkg/compose/down_test.go

@@ -40,7 +40,7 @@ func TestDown(t *testing.T) {
 	tested.dockerCli = cli
 	cli.EXPECT().Client().Return(api).AnyTimes()
 
-	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
+	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
 		[]moby.Container{
 			testContainer("service1", "123", false),
 			testContainer("service2", "456", false),
@@ -88,7 +88,7 @@ func TestDownRemoveOrphans(t *testing.T) {
 	tested.dockerCli = cli
 	cli.EXPECT().Client().Return(api).AnyTimes()
 
-	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
+	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(true)).Return(
 		[]moby.Container{
 			testContainer("service1", "123", false),
 			testContainer("service2", "789", false),
@@ -125,7 +125,7 @@ func TestDownRemoveVolumes(t *testing.T) {
 	tested.dockerCli = cli
 	cli.EXPECT().Client().Return(api).AnyTimes()
 
-	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
+	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
 		[]moby.Container{testContainer("service1", "123", false)}, nil)
 	api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
 		Return(volume.VolumeListOKBody{

+ 68 - 0
pkg/compose/envresolver.go

@@ -0,0 +1,68 @@
+/*
+   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 (
+	"runtime"
+	"strings"
+)
+
+var (
+	// isCaseInsensitiveEnvVars is true on platforms where environment variable names are treated case-insensitively.
+	isCaseInsensitiveEnvVars = (runtime.GOOS == "windows")
+)
+
+// envResolver returns resolver for environment variables suitable for the current platform.
+// Expected to be used with `MappingWithEquals.Resolve`.
+// Updates in `environment` may not be reflected.
+func envResolver(environment map[string]string) func(string) (string, bool) {
+	return envResolverWithCase(environment, isCaseInsensitiveEnvVars)
+}
+
+// envResolverWithCase returns resolver for environment variables with the specified case-sensitive condition.
+// Expected to be used with `MappingWithEquals.Resolve`.
+// Updates in `environment` may not be reflected.
+func envResolverWithCase(environment map[string]string, caseInsensitive bool) func(string) (string, bool) {
+	if environment == nil {
+		return func(s string) (string, bool) {
+			return "", false
+		}
+	}
+	if !caseInsensitive {
+		return func(s string) (string, bool) {
+			v, ok := environment[s]
+			return v, ok
+		}
+	}
+	// variable names must be treated case-insensitively.
+	// Resolves in this way:
+	// * Return the value if its name matches with the passed name case-sensitively.
+	// * Otherwise, return the value if its lower-cased name matches lower-cased passed name.
+	//     * The value is indefinite if multiple variable matches.
+	loweredEnvironment := make(map[string]string, len(environment))
+	for k, v := range environment {
+		loweredEnvironment[strings.ToLower(k)] = v
+	}
+	return func(s string) (string, bool) {
+		v, ok := environment[s]
+		if ok {
+			return v, ok
+		}
+		v, ok = loweredEnvironment[strings.ToLower(s)]
+		return v, ok
+	}
+}

+ 115 - 0
pkg/compose/envresolver_test.go

@@ -0,0 +1,115 @@
+/*
+   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 (
+	"testing"
+
+	"gotest.tools/assert"
+)
+
+func Test_EnvResolverWithCase(t *testing.T) {
+	tests := []struct {
+		name            string
+		environment     map[string]string
+		caseInsensitive bool
+		search          string
+		expectedValue   string
+		expectedOk      bool
+	}{
+		{
+			name: "case sensitive/case match",
+			environment: map[string]string{
+				"Env1": "Value1",
+				"Env2": "Value2",
+			},
+			caseInsensitive: false,
+			search:          "Env1",
+			expectedValue:   "Value1",
+			expectedOk:      true,
+		},
+		{
+			name: "case sensitive/case unmatch",
+			environment: map[string]string{
+				"Env1": "Value1",
+				"Env2": "Value2",
+			},
+			caseInsensitive: false,
+			search:          "ENV1",
+			expectedValue:   "",
+			expectedOk:      false,
+		},
+		{
+			name:            "case sensitive/nil environment",
+			environment:     nil,
+			caseInsensitive: false,
+			search:          "Env1",
+			expectedValue:   "",
+			expectedOk:      false,
+		},
+		{
+			name: "case insensitive/case match",
+			environment: map[string]string{
+				"Env1": "Value1",
+				"Env2": "Value2",
+			},
+			caseInsensitive: true,
+			search:          "Env1",
+			expectedValue:   "Value1",
+			expectedOk:      true,
+		},
+		{
+			name: "case insensitive/case unmatch",
+			environment: map[string]string{
+				"Env1": "Value1",
+				"Env2": "Value2",
+			},
+			caseInsensitive: true,
+			search:          "ENV1",
+			expectedValue:   "Value1",
+			expectedOk:      true,
+		},
+		{
+			name: "case insensitive/unmatch",
+			environment: map[string]string{
+				"Env1": "Value1",
+				"Env2": "Value2",
+			},
+			caseInsensitive: true,
+			search:          "Env3",
+			expectedValue:   "",
+			expectedOk:      false,
+		},
+		{
+			name:            "case insensitive/nil environment",
+			environment:     nil,
+			caseInsensitive: true,
+			search:          "Env1",
+			expectedValue:   "",
+			expectedOk:      false,
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			f := envResolverWithCase(test.environment, test.caseInsensitive)
+			v, ok := f(test.search)
+			assert.Equal(t, v, test.expectedValue)
+			assert.Equal(t, ok, test.expectedOk)
+		})
+	}
+}

+ 1 - 1
pkg/compose/hash.go

@@ -23,7 +23,7 @@ import (
 	"github.com/opencontainers/go-digest"
 )
 
-// ServiceHash compute configuration has for a service
+// ServiceHash computes the configuration hash for a service.
 func ServiceHash(o types.ServiceConfig) (string, error) {
 	// remove the Build config when generating the service hash
 	o.Build = nil

+ 9 - 2
pkg/compose/kill_test.go

@@ -18,6 +18,7 @@ package compose
 
 import (
 	"context"
+	"fmt"
 	"path/filepath"
 	"strings"
 	"testing"
@@ -110,9 +111,15 @@ func anyCancellableContext() gomock.Matcher {
 	return gomock.AssignableToTypeOf(ctxWithCancel)
 }
 
-func projectFilterListOpt() moby.ContainerListOptions {
+func projectFilterListOpt(withOneOff bool) moby.ContainerListOptions {
+	filter := filters.NewArgs(
+		projectFilter(strings.ToLower(testProject)),
+	)
+	if !withOneOff {
+		filter.Add("label", fmt.Sprintf("%s=False", compose.OneoffLabel))
+	}
 	return moby.ContainerListOptions{
-		Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
+		Filters: filter,
 		All:     true,
 	}
 }

+ 1 - 1
pkg/compose/logs.go

@@ -95,7 +95,7 @@ func (s *composeService) logContainers(ctx context.Context, consumer api.LogCons
 	if err != nil {
 		return err
 	}
-	defer r.Close() // nolint errcheck
+	defer r.Close() //nolint errcheck
 
 	name := getContainerNameWithoutProject(c)
 	w := utils.GetWriter(func(line string) {

+ 2 - 2
pkg/compose/ls.go

@@ -106,9 +106,9 @@ func combinedStatus(statuses []string) string {
 	for _, status := range keys {
 		nb := nbByStatus[status]
 		if result != "" {
-			result = result + ", "
+			result += ", "
 		}
-		result = result + fmt.Sprintf("%s(%d)", status, nb)
+		result += fmt.Sprintf("%s(%d)", status, nb)
 	}
 	return result
 }

+ 2 - 2
pkg/compose/metrics.go

@@ -50,13 +50,13 @@ var (
 	ComposeParseFailure = FailureCategory{MetricsStatus: ComposeParseFailureStatus, ExitCode: 15}
 	// CommandSyntaxFailure failure for command line syntax
 	CommandSyntaxFailure = FailureCategory{MetricsStatus: CommandSyntaxFailureStatus, ExitCode: 16}
-	//BuildFailure failure while building images.
+	// BuildFailure failure while building images.
 	BuildFailure = FailureCategory{MetricsStatus: BuildFailureStatus, ExitCode: 17}
 	// PullFailure failure while pulling image
 	PullFailure = FailureCategory{MetricsStatus: PullFailureStatus, ExitCode: 18}
 )
 
-//ByExitCode retrieve FailureCategory based on command exit code
+// ByExitCode retrieve FailureCategory based on command exit code
 func ByExitCode(exitCode int) FailureCategory {
 	switch exitCode {
 	case 0:

+ 10 - 2
pkg/compose/pause.go

@@ -33,12 +33,16 @@ func (s *composeService) Pause(ctx context.Context, projectName string, options
 	})
 }
 
-func (s *composeService) pause(ctx context.Context, project string, options api.PauseOptions) error {
-	containers, err := s.getContainers(ctx, project, oneOffExclude, false, options.Services...)
+func (s *composeService) pause(ctx context.Context, projectName string, options api.PauseOptions) error {
+	containers, err := s.getContainers(ctx, projectName, oneOffExclude, false, options.Services...)
 	if err != nil {
 		return err
 	}
 
+	if options.Project != nil {
+		containers = containers.filter(isService(options.Project.ServiceNames()...))
+	}
+
 	w := progress.ContextWriter(ctx)
 	eg, ctx := errgroup.WithContext(ctx)
 	containers.forEach(func(container moby.Container) {
@@ -67,6 +71,10 @@ func (s *composeService) unPause(ctx context.Context, projectName string, option
 		return err
 	}
 
+	if options.Project != nil {
+		containers = containers.filter(isService(options.Project.ServiceNames()...))
+	}
+
 	w := progress.ContextWriter(ctx)
 	eg, ctx := errgroup.WithContext(ctx)
 	containers.forEach(func(container moby.Container) {

+ 5 - 5
pkg/compose/printer.go

@@ -32,6 +32,11 @@ type logPrinter interface {
 	Cancel()
 }
 
+type printer struct {
+	queue    chan api.ContainerEvent
+	consumer api.LogConsumer
+}
+
 // newLogPrinter builds a LogPrinter passing containers logs to LogConsumer
 func newLogPrinter(consumer api.LogConsumer) logPrinter {
 	queue := make(chan api.ContainerEvent)
@@ -48,11 +53,6 @@ func (p *printer) Cancel() {
 	}
 }
 
-type printer struct {
-	queue    chan api.ContainerEvent
-	consumer api.LogConsumer
-}
-
 func (p *printer) HandleEvent(event api.ContainerEvent) {
 	p.queue <- event
 }

+ 13 - 0
pkg/compose/ps.go

@@ -37,6 +37,19 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api
 		return nil, err
 	}
 
+	project := options.Project
+	if project == nil {
+		project, err = s.getProjectWithResources(ctx, containers, projectName)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	if len(options.Services) == 0 {
+		options.Services = project.ServiceNames()
+	}
+
+	containers = containers.filter(isService(options.Services...))
 	summary := make([]api.ContainerSummary, len(containers))
 	eg, ctx := errgroup.WithContext(ctx)
 	for i, container := range containers {

+ 3 - 0
pkg/compose/ps_test.go

@@ -26,6 +26,7 @@ import (
 
 	moby "github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/api/types/volume"
 
 	compose "github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/mocks"
@@ -48,6 +49,8 @@ func TestPs(t *testing.T) {
 	c2, inspect2 := containerDetails("service1", "456", "running", "", 0)
 	c2.Ports = []moby.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}}
 	c3, inspect3 := containerDetails("service2", "789", "exited", "", 130)
+	api.EXPECT().VolumeList(ctx, gomock.Any()).Return(volume.VolumeListOKBody{}, nil)
+	api.EXPECT().NetworkList(ctx, gomock.Any()).Return([]moby.NetworkResource{}, nil)
 	api.EXPECT().ContainerList(ctx, listOpts).Return([]moby.Container{c1, c2, c3}, nil)
 	api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil)
 	api.EXPECT().ContainerInspect(anyCancellableContext(), "456").Return(inspect2, nil)

+ 5 - 1
pkg/compose/remove.go

@@ -31,7 +31,7 @@ import (
 
 func (s *composeService) Remove(ctx context.Context, projectName string, options api.RemoveOptions) error {
 	projectName = strings.ToLower(projectName)
-	containers, _, err := s.actualState(ctx, projectName, options.Services)
+	containers, err := s.getContainers(ctx, projectName, oneOffExclude, true, options.Services...)
 	if err != nil {
 		if api.IsNotFoundError(err) {
 			fmt.Fprintln(s.stderr(), "No stopped containers")
@@ -40,6 +40,10 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
 		return err
 	}
 
+	if options.Project != nil {
+		containers = containers.filter(isService(options.Project.ServiceNames()...))
+	}
+
 	stoppedContainers := containers.filter(func(c moby.Container) bool {
 		return c.State != ContainerRunning
 	})

+ 9 - 11
pkg/compose/restart.go

@@ -34,15 +34,17 @@ func (s *composeService) Restart(ctx context.Context, projectName string, option
 }
 
 func (s *composeService) restart(ctx context.Context, projectName string, options api.RestartOptions) error {
-
-	observedState, err := s.getContainers(ctx, projectName, oneOffExclude, true)
+	containers, err := s.getContainers(ctx, projectName, oneOffExclude, true)
 	if err != nil {
 		return err
 	}
 
-	project, err := s.projectFromName(observedState, projectName, options.Services...)
-	if err != nil {
-		return err
+	project := options.Project
+	if project == nil {
+		project, err = s.getProjectWithResources(ctx, containers, projectName)
+		if err != nil {
+			return err
+		}
 	}
 
 	if len(options.Services) == 0 {
@@ -50,12 +52,12 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
 	}
 
 	w := progress.ContextWriter(ctx)
-	err = InDependencyOrder(ctx, project, func(c context.Context, service string) error {
+	return InDependencyOrder(ctx, project, func(c context.Context, service string) error {
 		if !utils.StringContains(options.Services, service) {
 			return nil
 		}
 		eg, ctx := errgroup.WithContext(ctx)
-		for _, container := range observedState.filter(isService(service)) {
+		for _, container := range containers.filter(isService(service)) {
 			container := container
 			eg.Go(func() error {
 				eventName := getContainerProgressName(container)
@@ -69,8 +71,4 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
 		}
 		return eg.Wait()
 	})
-	if err != nil {
-		return err
-	}
-	return nil
 }

+ 4 - 7
pkg/compose/run.go

@@ -114,15 +114,12 @@ func applyRunOptions(project *types.Project, service *types.ServiceConfig, opts
 		service.Entrypoint = opts.Entrypoint
 	}
 	if len(opts.Environment) > 0 {
-		env := types.NewMappingWithEquals(opts.Environment)
-		projectEnv := env.Resolve(func(s string) (string, bool) {
-			if _, ok := service.Environment[s]; ok {
-				return "", false
-			}
-			v, ok := project.Environment[s]
+		cmdEnv := types.NewMappingWithEquals(opts.Environment)
+		serviceOverrideEnv := cmdEnv.Resolve(func(s string) (string, bool) {
+			v, ok := envResolver(project.Environment)(s)
 			return v, ok
 		}).RemoveEmpty()
-		service.Environment.OverrideBy(projectEnv)
+		service.Environment.OverrideBy(serviceOverrideEnv)
 	}
 	for k, v := range opts.Labels {
 		service.Labels = service.Labels.Add(k, v)

+ 1 - 1
pkg/compose/secrets.go

@@ -57,7 +57,7 @@ func createTar(env string, config types.ServiceSecretConfig) (bytes.Buffer, erro
 	value := []byte(env)
 	b := bytes.Buffer{}
 	tarWriter := tar.NewWriter(&b)
-	mode := uint32(0400)
+	mode := uint32(0o400)
 	if config.Mode != nil {
 		mode = *config.Mode
 	}

+ 19 - 5
pkg/compose/stop.go

@@ -22,6 +22,7 @@ import (
 
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/progress"
+	"github.com/docker/compose/v2/pkg/utils"
 )
 
 func (s *composeService) Stop(ctx context.Context, projectName string, options api.StopOptions) error {
@@ -31,15 +32,28 @@ func (s *composeService) Stop(ctx context.Context, projectName string, options a
 }
 
 func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error {
-	w := progress.ContextWriter(ctx)
-
-	containers, project, err := s.actualState(ctx, projectName, options.Services)
+	containers, err := s.getContainers(ctx, projectName, oneOffExclude, true)
 	if err != nil {
 		return err
 	}
 
+	project := options.Project
+	if project == nil {
+		project, err = s.getProjectWithResources(ctx, containers, projectName)
+		if err != nil {
+			return err
+		}
+	}
+
+	if len(options.Services) == 0 {
+		options.Services = project.ServiceNames()
+	}
+
+	w := progress.ContextWriter(ctx)
 	return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error {
-		containersToStop := containers.filter(isService(service)).filter(isNotOneOff)
-		return s.stopContainers(ctx, w, containersToStop, options.Timeout)
+		if !utils.StringContains(options.Services, service) {
+			return nil
+		}
+		return s.stopContainers(ctx, w, containers.filter(isService(service)).filter(isNotOneOff), options.Timeout)
 	})
 }

+ 7 - 1
pkg/compose/stop_test.go

@@ -26,6 +26,8 @@ import (
 	"github.com/docker/compose/v2/pkg/mocks"
 
 	moby "github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/api/types/volume"
 	"github.com/golang/mock/gomock"
 	"gotest.tools/v3/assert"
 )
@@ -40,12 +42,16 @@ func TestStopTimeout(t *testing.T) {
 	cli.EXPECT().Client().Return(api).AnyTimes()
 
 	ctx := context.Background()
-	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
+	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
 		[]moby.Container{
 			testContainer("service1", "123", false),
 			testContainer("service1", "456", false),
 			testContainer("service2", "789", false),
 		}, nil)
+	api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
+		Return(volume.VolumeListOKBody{}, nil)
+	api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
+		Return([]moby.NetworkResource{}, nil)
 
 	timeout := time.Duration(2) * time.Second
 	api.EXPECT().ContainerStop(gomock.Any(), "123", &timeout).Return(nil)

+ 4 - 4
pkg/compose/up.go

@@ -60,13 +60,13 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
 		return progress.Run(ctx, func(ctx context.Context) error {
 			go func() {
 				<-signalChan
-				s.Kill(ctx, project.Name, api.KillOptions{ // nolint:errcheck
-					Services: project.ServiceNames(),
+				s.Kill(ctx, project.Name, api.KillOptions{ //nolint:errcheck
+					Services: options.Create.Services,
 				})
 			}()
 
 			return s.Stop(ctx, project.Name, api.StopOptions{
-				Services: project.ServiceNames(),
+				Services: options.Create.Services,
 			})
 		})
 	}
@@ -74,7 +74,7 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
 		<-signalChan
 		printer.Cancel()
 		fmt.Println("Gracefully stopping... (press Ctrl+C again to force)")
-		stopFunc() // nolint:errcheck
+		stopFunc() //nolint:errcheck
 	}()
 
 	var exitCode int

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini