瀏覽代碼

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

Vedant Koditkar 3 年之前
父節點
當前提交
e623b5ca1e
共有 100 個文件被更改,包括 2518 次插入2220 次删除
  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"'
         description: 'To run with tmate enter "debug_enabled"'
         required: false
         required: false
         default: "false"
         default: "false"
-
+env:
+  GO_VERSION: 1.18.5
+  DOCKER_CLI_VERSION: 20.10.17
 jobs:
 jobs:
   lint:
   lint:
     name: Lint
     name: Lint
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
-    env:
-      GO111MODULE: "on"
     steps:
     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
       - 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
       - name: Validate go-mod, license headers and docs are up-to-date
         run: make validate
         run: make validate
@@ -34,8 +34,9 @@ jobs:
       - name: Run golangci-lint
       - name: Run golangci-lint
         env:
         env:
           BUILD_TAGS: e2e
           BUILD_TAGS: e2e
-        uses: golangci/golangci-lint-action@v2
+        uses: golangci/golangci-lint-action@v3
         with:
         with:
+          version: v1.47.3
           args: --timeout=180s
           args: --timeout=180s
 
 
   # only on main branch, costs too much for the gain on every PR
   # only on main branch, costs too much for the gain on every PR
@@ -43,22 +44,15 @@ jobs:
     name: Validate cross build
     name: Validate cross build
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     if: github.ref == 'refs/heads/main'
     if: github.ref == 'refs/heads/main'
-    env:
-      GO111MODULE: "on"
     steps:
     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
       - 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:
         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.
       # 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
       # Time used to build linux here is gained back in the build for local E2E step
@@ -68,28 +62,21 @@ jobs:
   build-plugin:
   build-plugin:
     name: Build and tests in plugin mode
     name: Build and tests in plugin mode
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
-    env:
-      GO111MODULE: "on"
     steps:
     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:
         with:
-          go-version: 1.18.3
-        id: go
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
 
 
       - name: Setup docker CLI
       - name: Setup docker CLI
         run: |
         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
           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
       - name: Test
         run: make -f builder.Makefile test
         run: make -f builder.Makefile test
 
 
@@ -104,28 +91,21 @@ jobs:
   build-standalone:
   build-standalone:
     name: Build and tests in standalone mode
     name: Build and tests in standalone mode
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
-    env:
-      GO111MODULE: "on"
     steps:
     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:
         with:
-          go-version: 1.18.3
-        id: go
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
 
 
       - name: Setup docker CLI
       - name: Setup docker CLI
         run: |
         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
           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
       - name: Build for local E2E
         env:
         env:
           BUILD_TAGS: e2e
           BUILD_TAGS: e2e

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

@@ -40,6 +40,7 @@ jobs:
         uses: peter-evans/create-pull-request@923ad837f191474af6b1721408744feb989a4c27 # v4.0.4
         uses: peter-evans/create-pull-request@923ad837f191474af6b1721408744feb989a4c27 # v4.0.4
         with:
         with:
           token: ${{ secrets.GHPAT_DOCS_DISPATCH }}
           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 }}
           commit-message: Update Compose reference API to ${{ github.event.release.name }}
           signoff: true
           signoff: true
           branch: dispatch/compose-api-reference-${{ github.event.release.name }}
           branch: dispatch/compose-api-reference-${{ github.event.release.name }}
@@ -47,5 +48,4 @@ jobs:
           title: Update Compose reference API to ${{ github.event.release.name }}
           title: Update Compose reference API to ${{ github.event.release.name }}
           body: |
           body: |
             Update the Compose reference API documentation to keep in sync with the latest release `${{ github.event.release.name }}`
             Update the Compose reference API documentation to keep in sync with the latest release `${{ github.event.release.name }}`
-          labels: area/Compose
           draft: false
           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
     runs-on: ubuntu-latest
     steps:
     steps:
       - name: Checkout the latest code
       - name: Checkout the latest code
-        uses: actions/checkout@v2
+        uses: actions/checkout@v3
         with:
         with:
           token: ${{ secrets.GITHUB_TOKEN }}
           token: ${{ secrets.GITHUB_TOKEN }}
           fetch-depth: 0 # otherwise, you will fail to push refs to dest repo
           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:
       tag:
         description: "Release Tag"
         description: "Release Tag"
         required: true
         required: true
-
+env:
+  GO_VERSION: 1.18.5
 jobs:
 jobs:
   upload-release:
   upload-release:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     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:
         with:
-          go-version: 1.18.3
-        id: go
+          go-version: ${{ env.GO_VERSION }}
+          cache: true
 
 
       - name: Setup docker CLI
       - name: Setup docker CLI
         run: |
         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
           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
       - name: Build
         run: make GIT_TAG=${{ github.event.inputs.tag }} -f builder.Makefile cross
         run: make GIT_TAG=${{ github.event.inputs.tag }} -f builder.Makefile cross
 
 

+ 12 - 0
.golangci.yml

@@ -7,6 +7,7 @@ linters:
     - deadcode
     - deadcode
     - depguard
     - depguard
     - errcheck
     - errcheck
+    - gocritic
     - gocyclo
     - gocyclo
     - gofmt
     - gofmt
     - goimports
     - goimports
@@ -32,6 +33,17 @@ linters-settings:
       # The io/ioutil package has been deprecated.
       # The io/ioutil package has been deprecated.
       # https://go.dev/doc/go1.16#ioutil
       # https://go.dev/doc/go1.16#ioutil
       - io/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:
   gocyclo:
     min-complexity: 16
     min-complexity: 16
   lll:
   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`.
 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
 ```console
 make e2e-compose
 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
 ## Releases
 
 

+ 4 - 3
CONTRIBUTING.md

@@ -124,9 +124,10 @@ Fork the repository and make changes on your fork in a feature branch:
     issue.
     issue.
 
 
 Submit unit tests for your changes. Go has a great test framework built in; use
 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,
 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
 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
 #   Copyright 2020 Docker Compose CLI authors
@@ -15,10 +15,12 @@
 #   See the License for the specific language governing permissions and
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 #   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
 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
 FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION} AS base
 WORKDIR /compose-cli
 WORKDIR /compose-cli
 RUN apk add --no-cache -vv \
 RUN apk add --no-cache -vv \
@@ -34,7 +36,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \
 
 
 FROM base AS lint
 FROM base AS lint
 ENV CGO_ENABLED=0
 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 BUILD_TAGS
 ARG GIT_TAG
 ARG GIT_TAG
 RUN --mount=target=. \
 RUN --mount=target=. \
@@ -88,7 +90,7 @@ RUN --mount=target=. \
     make -f builder.Makefile test
     make -f builder.Makefile test
 
 
 FROM base AS check-license-headers
 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=. \
 RUN --mount=target=. \
     make -f builder.Makefile check-license-headers
     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
 	docker-compose version
 	go test $(TEST_FLAGS) -v -count=1 -parallel=1 --tags=standalone ./pkg/e2e
 	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
 .PHONY: mocks
 mocks:
 mocks:
 	mockgen -destination pkg/mocks/mock_docker_cli.go -package mocks github.com/docker/cli/cli/command Cli
 	mockgen -destination pkg/mocks/mock_docker_cli.go -package mocks github.com/docker/cli/cli/command Cli
@@ -60,6 +66,9 @@ mocks:
 .PHONY: e2e
 .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
 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
 .PHONY: cross
 cross: ## Compile the CLI for linux, darwin and windows
 cross: ## Compile the CLI for linux, darwin and windows
 	@docker build . --target cross \
 	@docker build . --target cross \
@@ -90,7 +99,7 @@ docs: ## generate documentation
 	$(eval $@_TMP_OUT := $(shell mktemp -d -t dockercli-output.XXXXXXXXXX))
 	$(eval $@_TMP_OUT := $(shell mktemp -d -t dockercli-output.XXXXXXXXXX))
 	docker build . \
 	docker build . \
 	--output type=local,dest=$($@_TMP_OUT) \
 	--output type=local,dest=$($@_TMP_OUT) \
-	-f ./docs/docs.Dockerfile \
+	-f ./docs/Dockerfile \
 	--target update
 	--target update
 	rm -rf ./docs/internal
 	rm -rf ./docs/internal
 	cp -R "$($@_TMP_OUT)"/out/* ./docs/
 	cp -R "$($@_TMP_OUT)"/out/* ./docs/
@@ -99,7 +108,7 @@ docs: ## generate documentation
 .PHONY: validate-docs
 .PHONY: validate-docs
 validate-docs: ## validate the doc does not change
 validate-docs: ## validate the doc does not change
 	@docker build . \
 	@docker build . \
-	-f ./docs/docs.Dockerfile \
+	-f ./docs/Dockerfile \
 	--target validate
 	--target validate
 
 
 .PHONY: check-dependencies
 .PHONY: check-dependencies

+ 1 - 1
cmd/compose/build.go

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

+ 37 - 21
cmd/compose/compose.go

@@ -136,6 +136,24 @@ func (o *projectOptions) addProjectFlags(f *pflag.FlagSet) {
 	_ = f.MarkHidden("workdir")
 	_ = 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) {
 func (o *projectOptions) toProjectName() (string, error) {
 	if o.ProjectName != "" {
 	if o.ProjectName != "" {
 		return o.ProjectName, nil
 		return o.ProjectName, nil
@@ -159,15 +177,15 @@ func (o *projectOptions) toProject(services []string, po ...cli.ProjectOptionsFn
 		return nil, compose.WrapComposeError(err)
 		return nil, compose.WrapComposeError(err)
 	}
 	}
 
 
+	if o.Compatibility || utils.StringToBool(options.Environment["COMPOSE_COMPATIBILITY"]) {
+		api.Separator = "_"
+	}
+
 	project, err := cli.ProjectFromOptions(options)
 	project, err := cli.ProjectFromOptions(options)
 	if err != nil {
 	if err != nil {
 		return nil, compose.WrapComposeError(err)
 		return nil, compose.WrapComposeError(err)
 	}
 	}
 
 
-	if o.Compatibility || utils.StringToBool(project.Environment["COMPOSE_COMPATIBILITY"]) {
-		compose.Separator = "_"
-	}
-
 	ef := o.EnvFile
 	ef := o.EnvFile
 	if ef != "" && !filepath.IsAbs(ef) {
 	if ef != "" && !filepath.IsAbs(ef) {
 		ef, err = filepath.Abs(ef)
 		ef, err = filepath.Abs(ef)
@@ -239,11 +257,11 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
 		verbose bool
 		verbose bool
 		version bool
 		version bool
 	)
 	)
-	command := &cobra.Command{
+	c := &cobra.Command{
 		Short:            "Docker Compose",
 		Short:            "Docker Compose",
 		Use:              PluginName,
 		Use:              PluginName,
 		TraverseChildren: true,
 		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 {
 		RunE: func(cmd *cobra.Command, args []string) error {
 			if len(args) == 0 {
 			if len(args) == 0 {
 				return cmd.Help()
 				return cmd.Help()
@@ -300,7 +318,7 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
 		},
 		},
 	}
 	}
 
 
-	command.AddCommand(
+	c.AddCommand(
 		upCommand(&opts, backend),
 		upCommand(&opts, backend),
 		downCommand(&opts, backend),
 		downCommand(&opts, backend),
 		startCommand(&opts, backend),
 		startCommand(&opts, backend),
@@ -327,16 +345,16 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
 		createCommand(&opts, backend),
 		createCommand(&opts, backend),
 		copyCommand(&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 {
 func setEnvWithDotEnv(prjOpts *projectOptions) error {
@@ -354,10 +372,8 @@ func setEnvWithDotEnv(prjOpts *projectOptions) error {
 		return err
 		return err
 	}
 	}
 	for k, v := range envFromFile {
 	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
 	return nil

+ 1 - 1
cmd/compose/convert.go

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

+ 16 - 2
cmd/compose/create.go

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

+ 6 - 14
cmd/compose/down.go

@@ -22,7 +22,6 @@ import (
 	"os"
 	"os"
 	"time"
 	"time"
 
 
-	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/compose/v2/pkg/utils"
 	"github.com/docker/compose/v2/pkg/utils"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 	"github.com/spf13/cobra"
@@ -45,7 +44,7 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 		projectOptions: p,
 	}
 	}
 	downCmd := &cobra.Command{
 	downCmd := &cobra.Command{
-		Use:   "down",
+		Use:   "down [OPTIONS]",
 		Short: "Stop and remove containers, networks",
 		Short: "Stop and remove containers, networks",
 		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
 		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
 			opts.timeChanged = cmd.Flags().Changed("timeout")
 			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"))
 	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.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.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.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 {
 	flags.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
-		switch name {
-		case "volume":
+		if name == "volume" {
 			name = "volumes"
 			name = "volumes"
 			logrus.Warn("--volume is deprecated, please use --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 {
 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
 	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{
 	cmd := &cobra.Command{
-		Use:   "events [options] [--] [SERVICE...]",
+		Use:   "events [OPTIONS] [SERVICE...]",
 		Short: "Receive real time events from containers.",
 		Short: "Receive real time events from containers.",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runEvents(ctx, backend, opts, args)
 			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 {
 func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, services []string) error {
-	project, err := opts.toProjectName()
+	name, err := opts.toProjectName()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	return backend.Events(ctx, project, api.EventsOptions{
+	return backend.Events(ctx, name, api.EventsOptions{
 		Services: services,
 		Services: services,
 		Consumer: func(event api.Event) error {
 		Consumer: func(event api.Event) error {
 			if opts.json {
 			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{
 	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.",
 		Short: "Execute a command in a running container.",
 		Args:  cobra.MinimumNArgs(2),
 		Args:  cobra.MinimumNArgs(2),
 		PreRunE: Adapt(func(ctx context.Context, args []string) error {
 		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,
 		projectOptions: p,
 	}
 	}
 	imgCmd := &cobra.Command{
 	imgCmd := &cobra.Command{
-		Use:   "images [SERVICE...]",
+		Use:   "images [OPTIONS] [SERVICE...]",
 		Short: "List images used by the created containers",
 		Short: "List images used by the created containers",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runImages(ctx, backend, opts, args)
 			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,
 		projectOptions: p,
 	}
 	}
 	cmd := &cobra.Command{
 	cmd := &cobra.Command{
-		Use:   "kill [options] [SERVICE...]",
+		Use:   "kill [OPTIONS] [SERVICE...]",
 		Short: "Force stop service containers.",
 		Short: "Force stop service containers.",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runKill(ctx, backend, opts, args)
 			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 {
 func runKill(ctx context.Context, backend api.Service, opts killOptions, services []string) error {
-	projectName, err := opts.toProjectName()
+	name, err := opts.toProjectName()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	return backend.Kill(ctx, projectName, api.KillOptions{
+	return backend.Kill(ctx, name, api.KillOptions{
 		Services: services,
 		Services: services,
 		Signal:   opts.signal,
 		Signal:   opts.signal,
 	})
 	})

+ 13 - 12
cmd/compose/list.go

@@ -39,19 +39,20 @@ type lsOptions struct {
 }
 }
 
 
 func listCommand(backend api.Service) *cobra.Command {
 func listCommand(backend api.Service) *cobra.Command {
-	opts := lsOptions{Filter: opts.NewFilterOpt()}
+	lsOpts := lsOptions{Filter: opts.NewFilterOpt()}
 	lsCmd := &cobra.Command{
 	lsCmd := &cobra.Command{
-		Use:   "ls",
+		Use:   "ls [OPTIONS]",
 		Short: "List running compose projects",
 		Short: "List running compose projects",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 		RunE: Adapt(func(ctx context.Context, args []string) error {
-			return runList(ctx, backend, opts)
+			return runList(ctx, backend, lsOpts)
 		}),
 		}),
+		Args:              cobra.NoArgs,
 		ValidArgsFunction: noCompletion(),
 		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
 	return lsCmd
 }
 }
@@ -60,18 +61,18 @@ var acceptedListFilters = map[string]bool{
 	"name": true,
 	"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)
 	err := filters.Validate(acceptedListFilters)
 	if err != nil {
 	if err != nil {
 		return err
 		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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	if opts.Quiet {
+	if lsOpts.Quiet {
 		for _, s := range stackList {
 		for _, s := range stackList {
 			fmt.Println(s.Name)
 			fmt.Println(s.Name)
 		}
 		}
@@ -90,7 +91,7 @@ func runList(ctx context.Context, backend api.Service, opts lsOptions) error {
 	}
 	}
 
 
 	view := viewFromStackList(stackList)
 	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 {
 		for _, stack := range view {
 			_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", stack.Name, stack.Status, stack.ConfigFiles)
 			_, _ = 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,
 		projectOptions: p,
 	}
 	}
 	logsCmd := &cobra.Command{
 	logsCmd := &cobra.Command{
-		Use:   "logs [SERVICE...]",
+		Use:   "logs [OPTIONS] [SERVICE...]",
 		Short: "View output from containers",
 		Short: "View output from containers",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runLogs(ctx, backend, opts, args)
 			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 {
 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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	return backend.Pause(ctx, project, api.PauseOptions{
+	return backend.Pause(ctx, name, api.PauseOptions{
 		Services: services,
 		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 {
 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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	return backend.UnPause(ctx, project, api.PauseOptions{
+	return backend.UnPause(ctx, name, api.PauseOptions{
 		Services: services,
 		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,
 		projectOptions: p,
 	}
 	}
 	cmd := &cobra.Command{
 	cmd := &cobra.Command{
-		Use:   "port [options] [--] SERVICE PRIVATE_PORT",
+		Use:   "port [OPTIONS] SERVICE PRIVATE_PORT",
 		Short: "Print the public port for a port binding.",
 		Short: "Print the public port for a port binding.",
 		Args:  cobra.MinimumNArgs(2),
 		Args:  cobra.MinimumNArgs(2),
 		PreRunE: Adapt(func(ctx context.Context, args []string) error {
 		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,
 		projectOptions: p,
 	}
 	}
 	psCmd := &cobra.Command{
 	psCmd := &cobra.Command{
-		Use:   "ps [SERVICE...]",
+		Use:   "ps [OPTIONS] [SERVICE...]",
 		Short: "List containers",
 		Short: "List containers",
 		PreRunE: func(cmd *cobra.Command, args []string) error {
 		PreRunE: func(cmd *cobra.Command, args []string) error {
 			return opts.parseFilter()
 			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 {
 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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	containers, err := backend.Ps(ctx, projectName, api.PsOptions{
+	containers, err := backend.Ps(ctx, name, api.PsOptions{
+		Project:  project,
 		All:      opts.All,
 		All:      opts.All,
 		Services: services,
 		Services: services,
 	})
 	})

+ 1 - 1
cmd/compose/pull.go

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

+ 1 - 1
cmd/compose/push.go

@@ -36,7 +36,7 @@ func pushCommand(p *projectOptions, backend api.Service) *cobra.Command {
 		projectOptions: p,
 		projectOptions: p,
 	}
 	}
 	pushCmd := &cobra.Command{
 	pushCmd := &cobra.Command{
-		Use:   "push [SERVICE...]",
+		Use:   "push [OPTIONS] [SERVICE...]",
 		Short: "Push service images",
 		Short: "Push service images",
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runPush(ctx, backend, opts, args)
 			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,
 		projectOptions: p,
 	}
 	}
 	cmd := &cobra.Command{
 	cmd := &cobra.Command{
-		Use:   "rm [SERVICE...]",
+		Use:   "rm [OPTIONS] [SERVICE...]",
 		Short: "Removes stopped service containers",
 		Short: "Removes stopped service containers",
 		Long: `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 {
 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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	if opts.stop {
 	if opts.stop {
-		err := backend.Stop(ctx, project, api.StopOptions{
+		err := backend.Stop(ctx, name, api.StopOptions{
 			Services: services,
 			Services: services,
+			Project:  project,
 		})
 		})
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
 	}
 	}
 
 
-	return backend.Remove(ctx, project, api.RemoveOptions{
+	return backend.Remove(ctx, name, api.RemoveOptions{
 		Services: services,
 		Services: services,
 		Force:    opts.force,
 		Force:    opts.force,
 		Volumes:  opts.volumes,
 		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,
 		projectOptions: p,
 	}
 	}
 	restartCmd := &cobra.Command{
 	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 {
 		RunE: Adapt(func(ctx context.Context, args []string) error {
 			return runRestart(ctx, backend, opts, args)
 			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 {
 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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	timeout := time.Duration(opts.timeout) * time.Second
 	timeout := time.Duration(opts.timeout) * time.Second
-	return backend.Restart(ctx, projectName, api.RestartOptions{
+	return backend.Restart(ctx, name, api.RestartOptions{
 		Timeout:  &timeout,
 		Timeout:  &timeout,
 		Services: services,
 		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{
 	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.",
 		Short: "Run a one-off command on a service.",
 		Args:  cobra.MinimumNArgs(1),
 		Args:  cobra.MinimumNArgs(1),
 		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
 		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.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.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.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.user, "user", "u", "", "Run as specified username or uid")
 	flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
 	flags.StringVarP(&opts.workdir, "workdir", "w", "", "Working directory inside the container")
 	flags.StringVar(&opts.entrypoint, "entrypoint", "", "Override the entrypoint of the image")
 	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 {
 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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	return backend.Start(ctx, projectName, api.StartOptions{
+	return backend.Start(ctx, name, api.StartOptions{
 		AttachTo: services,
 		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,
 		projectOptions: p,
 	}
 	}
 	cmd := &cobra.Command{
 	cmd := &cobra.Command{
-		Use:   "stop [SERVICE...]",
+		Use:   "stop [OPTIONS] [SERVICE...]",
 		Short: "Stop services",
 		Short: "Stop services",
 		PreRun: func(cmd *cobra.Command, args []string) {
 		PreRun: func(cmd *cobra.Command, args []string) {
 			opts.timeChanged = cmd.Flags().Changed("timeout")
 			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 {
 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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -63,8 +63,9 @@ func runStop(ctx context.Context, backend api.Service, opts stopOptions, service
 		timeoutValue := time.Duration(opts.timeout) * time.Second
 		timeoutValue := time.Duration(opts.timeout) * time.Second
 		timeout = &timeoutValue
 		timeout = &timeoutValue
 	}
 	}
-	return backend.Stop(ctx, projectName, api.StopOptions{
+	return backend.Stop(ctx, name, api.StopOptions{
 		Timeout:  timeout,
 		Timeout:  timeout,
 		Services: services,
 		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{}
 	up := upOptions{}
 	create := createOptions{}
 	create := createOptions{}
 	upCmd := &cobra.Command{
 	upCmd := &cobra.Command{
-		Use:   "up [SERVICE...]",
+		Use:   "up [OPTIONS] [SERVICE...]",
 		Short: "Create and start containers",
 		Short: "Create and start containers",
 		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
 		PreRunE: AdaptCmd(func(ctx context.Context, cmd *cobra.Command, args []string) error {
 			create.timeChanged = cmd.Flags().Changed("timeout")
 			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.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.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.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.BoolVar(&create.removeOrphans, "remove-orphans", false, "Remove containers for services not defined in the Compose file.")
 	flags.StringArrayVar(&up.scale, "scale", []string{}, "Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.")
 	flags.StringArrayVar(&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.")
 	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 {
 func setServiceScale(project *types.Project, name string, replicas uint64) error {
 	for i, s := range project.Services {
 	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)
 	return fmt.Errorf("unknown service %q", name)
 }
 }

+ 7 - 2
cmd/compose/version.go

@@ -35,13 +35,18 @@ type versionOptions struct {
 func versionCommand() *cobra.Command {
 func versionCommand() *cobra.Command {
 	opts := versionOptions{}
 	opts := versionOptions{}
 	cmd := &cobra.Command{
 	cmd := &cobra.Command{
-		Use:   "version",
+		Use:   "version [OPTIONS]",
 		Short: "Show the Docker Compose version information",
 		Short: "Show the Docker Compose version information",
-		Args:  cobra.MaximumNArgs(0),
+		Args:  cobra.NoArgs,
 		RunE: func(cmd *cobra.Command, _ []string) error {
 		RunE: func(cmd *cobra.Command, _ []string) error {
 			runVersion(opts)
 			runVersion(opts)
 			return nil
 			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
 	// define flags for backward compatibility with com.docker.cli
 	flags := cmd.Flags()
 	flags := cmd.Flags()

+ 12 - 12
cmd/formatter/logs.go

@@ -27,6 +27,16 @@ import (
 	"github.com/docker/compose/v2/pkg/api"
 	"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
 // NewLogConsumer creates a new LogConsumer
 func NewLogConsumer(ctx context.Context, w io.Writer, color bool, prefix bool) api.LogConsumer {
 func NewLogConsumer(ctx context.Context, w io.Writer, color bool, prefix bool) api.LogConsumer {
 	return &logConsumer{
 	return &logConsumer{
@@ -79,14 +89,14 @@ func (l *logConsumer) Log(container, service, message string) {
 	}
 	}
 	p := l.getPresenter(container)
 	p := l.getPresenter(container)
 	for _, line := range strings.Split(message, "\n") {
 	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) {
 func (l *logConsumer) Status(container, msg string) {
 	p := l.getPresenter(container)
 	p := l.getPresenter(container)
 	s := p.colors(fmt.Sprintf("%s %s\n", container, msg))
 	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() {
 func (l *logConsumer) computeWidth() {
@@ -101,16 +111,6 @@ func (l *logConsumer) computeWidth() {
 	l.width = width + 1
 	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 {
 type presenter struct {
 	colors colorFunc
 	colors colorFunc
 	name   string
 	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
 #   Copyright 2020 Docker Compose CLI authors
@@ -15,7 +15,7 @@
 #   See the License for the specific language governing permissions and
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 #   limitations under the License.
 
 
-ARG GO_VERSION=1.18.3
+ARG GO_VERSION=1.18.5
 ARG FORMATS=md,yaml
 ARG FORMATS=md,yaml
 
 
 FROM --platform=${BUILDPLATFORM} golang:${GO_VERSION}-alpine AS docsgen
 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 |
 | [`ps`](compose_ps.md) | List containers |
 | [`pull`](compose_pull.md) | Pull service images |
 | [`pull`](compose_pull.md) | Pull service images |
 | [`push`](compose_push.md) | Push 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 |
 | [`rm`](compose_rm.md) | Removes stopped service containers |
 | [`run`](compose_run.md) | Run a one-off command on a service. |
 | [`run`](compose_run.md) | Run a one-off command on a service. |
 | [`start`](compose_start.md) | Start services |
 | [`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
 ### Aliases
 
 
-`convert`, `config`
+`docker compose convert`, `docker compose config`
 
 
 ### Options
 ### 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. |
 | `--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-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. |
 | `--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-->
 <!---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. |
 | `--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") |
 | `--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 |
 | `-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-->
 <!---MARKER_GEN_END-->

+ 1 - 1
docs/reference/compose_pull.md

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

+ 2 - 2
docs/reference/compose_restart.md

@@ -1,7 +1,7 @@
 # docker compose restart
 # docker compose restart
 
 
 <!---MARKER_GEN_START-->
 <!---MARKER_GEN_START-->
-Restart containers
+Restart service containers
 
 
 ### Options
 ### Options
 
 
@@ -14,7 +14,7 @@ Restart containers
 
 
 ## Description
 ## 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
 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 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 |
 | `-e`, `--env` | `stringArray` |  | Set environment variables |
 | `-i`, `--interactive` |  |  | Keep STDIN open even if not attached. |
 | `-i`, `--interactive` |  |  | Keep STDIN open even if not attached. |
 | `-l`, `--label` | `stringArray` |  | Add or override a label |
 | `-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). |
 | `-T`, `--no-TTY` |  |  | Disable pseudo-TTY allocation (default: auto-detected). |
 | `--no-deps` |  |  | Don't start linked services. |
 | `--no-deps` |  |  | Don't start linked services. |
 | `-p`, `--publish` | `stringArray` |  | Publish a container's port(s) to the host. |
 | `-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-log-prefix` |  |  | Don't print prefix in logs. |
 | `--no-recreate` |  |  | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
 | `--no-recreate` |  |  | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
 | `--no-start` |  |  | Don't start the services after creating them. |
 | `--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. |
 | `--quiet-pull` |  |  | Pull without printing progress information. |
 | `--remove-orphans` |  |  | Remove containers for services not defined in the Compose file. |
 | `--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. |
 | `-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
 command: docker compose
 short: Docker Compose
 short: Docker Compose
 long: |-
 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
 usage: docker compose
 pname: docker
 pname: docker
 plink: docker.yaml
 plink: docker.yaml
 cname:
 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:
 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:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 121 - 121
docs/reference/docker_compose_build.yaml

@@ -1,132 +1,132 @@
 command: docker compose build
 command: docker compose build
 short: Build or rebuild services
 short: Build or rebuild services
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 116 - 116
docs/reference/docker_compose_convert.yaml

@@ -1,126 +1,126 @@
 command: docker compose convert
 command: docker compose convert
-aliases: config
+aliases: docker compose convert, docker compose config
 short: Converts the compose file to platform's canonical format
 short: Converts the compose file to platform's canonical format
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 46 - 45
docs/reference/docker_compose_cp.yaml

@@ -1,54 +1,55 @@
 command: docker compose cp
 command: docker compose cp
 short: Copy files/folders between a service container and the local filesystem
 short: Copy files/folders between a service container and the local filesystem
 long: 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 53 - 43
docs/reference/docker_compose_create.yaml

@@ -1,52 +1,62 @@
 command: docker compose create
 command: docker compose create
 short: Creates containers for a service.
 short: Creates containers for a service.
 long: 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 53 - 53
docs/reference/docker_compose_down.yaml

@@ -1,66 +1,66 @@
 command: docker compose down
 command: docker compose down
 short: Stop and remove containers, networks
 short: Stop and remove containers, networks
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 27 - 27
docs/reference/docker_compose_events.yaml

@@ -1,39 +1,39 @@
 command: docker compose events
 command: docker compose events
 short: Receive real time events from containers.
 short: Receive real time events from containers.
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 101 - 101
docs/reference/docker_compose_exec.yaml

@@ -1,111 +1,111 @@
 command: docker compose exec
 command: docker compose exec
 short: Execute a command in a running container.
 short: Execute a command in a running container.
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 12 - 12
docs/reference/docker_compose_images.yaml

@@ -1,21 +1,21 @@
 command: docker compose images
 command: docker compose images
 short: List images used by the created containers
 short: List images used by the created containers
 long: 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 16 - 16
docs/reference/docker_compose_kill.yaml

@@ -1,26 +1,26 @@
 command: docker compose kill
 command: docker compose kill
 short: Force stop service containers.
 short: Force stop service containers.
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 74 - 74
docs/reference/docker_compose_logs.yaml

@@ -1,83 +1,83 @@
 command: docker compose logs
 command: docker compose logs
 short: View output from containers
 short: View output from containers
 long: Displays log output from services.
 long: Displays log output from services.
-usage: docker compose logs [SERVICE...]
+usage: docker compose logs [OPTIONS] [SERVICE...]
 pname: docker compose
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 42 - 42
docs/reference/docker_compose_ls.yaml

@@ -1,51 +1,51 @@
 command: docker compose ls
 command: docker compose ls
 short: List running compose projects
 short: List running compose projects
 long: List Compose projects running on platform.
 long: List Compose projects running on platform.
-usage: docker compose ls
+usage: docker compose ls [OPTIONS]
 pname: docker compose
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 1 - 1
docs/reference/docker_compose_pause.yaml

@@ -1,7 +1,7 @@
 command: docker compose pause
 command: docker compose pause
 short: Pause services
 short: Pause services
 long: |
 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...]
 usage: docker compose pause [SERVICE...]
 pname: docker compose
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml

+ 21 - 21
docs/reference/docker_compose_port.yaml

@@ -1,30 +1,30 @@
 command: docker compose port
 command: docker compose port
 short: Print the public port for a port binding.
 short: Print the public port for a port binding.
 long: Prints the public port for a port binding.
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 146 - 146
docs/reference/docker_compose_ps.yaml

@@ -1,170 +1,170 @@
 command: docker compose ps
 command: docker compose ps
 short: List containers
 short: List containers
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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: |-
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 91 - 91
docs/reference/docker_compose_pull.yaml

@@ -1,104 +1,104 @@
 command: docker compose pull
 command: docker compose pull
 short: Pull service images
 short: Pull service images
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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: |-
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 25 - 25
docs/reference/docker_compose_push.yaml

@@ -1,38 +1,38 @@
 command: docker compose push
 command: docker compose push
 short: Push service images
 short: Push service images
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 21 - 21
docs/reference/docker_compose_restart.yaml

@@ -1,31 +1,31 @@
 command: docker compose restart
 command: docker compose restart
-short: Restart containers
+short: Restart service containers
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 56 - 56
docs/reference/docker_compose_rm.yaml

@@ -1,69 +1,69 @@
 command: docker compose rm
 command: docker compose rm
 short: Removes stopped service containers
 short: Removes stopped service containers
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 216 - 217
docs/reference/docker_compose_run.yaml

@@ -1,242 +1,241 @@
 command: docker compose run
 command: docker compose run
 short: Run a one-off command on a service.
 short: Run a one-off command on a service.
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 13 - 13
docs/reference/docker_compose_stop.yaml

@@ -1,22 +1,22 @@
 command: docker compose stop
 command: docker compose stop
 short: Stop services
 short: Stop services
 long: |
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 6 - 6
docs/reference/docker_compose_top.yaml

@@ -5,12 +5,12 @@ usage: docker compose top [SERVICES...]
 pname: docker compose
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 examples: |-
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 231 - 221
docs/reference/docker_compose_up.yaml

@@ -1,235 +1,245 @@
 command: docker compose up
 command: docker compose up
 short: Create and start containers
 short: Create and start containers
 long: |-
 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 21 - 21
docs/reference/docker_compose_version.yaml

@@ -1,30 +1,30 @@
 command: docker compose version
 command: docker compose version
 short: Show the Docker Compose version information
 short: Show the Docker Compose version information
 long: 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
 pname: docker compose
 plink: docker_compose.yaml
 plink: docker_compose.yaml
 options:
 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
 deprecated: false
 experimental: false
 experimental: false
 experimentalcli: false
 experimentalcli: false

+ 12 - 13
go.mod

@@ -5,14 +5,14 @@ go 1.18
 require (
 require (
 	github.com/AlecAivazis/survey/v2 v2.3.5
 	github.com/AlecAivazis/survey/v2 v2.3.5
 	github.com/buger/goterm v1.0.4
 	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/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/buildx v0.8.2 // when updating, also update the replace rules accordingly
 	github.com/docker/cli v20.10.17+incompatible
 	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/docker v20.10.17+incompatible
 	github.com/docker/go-connections v0.4.0
 	github.com/docker/go-connections v0.4.0
 	github.com/docker/go-units 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/hashicorp/go-version v1.6.0
 	github.com/mattn/go-isatty v0.0.14
 	github.com/mattn/go-isatty v0.0.14
 	github.com/mattn/go-shellwords v1.0.12
 	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/moby/term v0.0.0-20210619224110-3f7ff695adc6
 	github.com/morikuni/aec v1.0.0
 	github.com/morikuni/aec v1.0.0
 	github.com/opencontainers/go-digest v1.0.0
 	github.com/opencontainers/go-digest v1.0.0
 	github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
 	github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
 	github.com/pkg/errors v0.9.1
 	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/cobra v1.5.0
 	github.com/spf13/pflag v1.0.5
 	github.com/spf13/pflag v1.0.5
 	github.com/stretchr/testify v1.8.0
 	github.com/stretchr/testify v1.8.0
 	github.com/theupdateframework/notary v0.7.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 v2.2.0+incompatible
 	gotest.tools/v3 v3.3.0
 	gotest.tools/v3 v3.3.0
 )
 )
@@ -45,7 +45,7 @@ require (
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/cnabio/cnab-go v0.23.4 // 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/ttrpc v1.1.0 // indirect
 	github.com/containerd/typeurl v1.0.2 // indirect
 	github.com/containerd/typeurl v1.0.2 // indirect
 	github.com/davecgh/go-spew v1.1.1 // 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/googleapis v1.4.1 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang/protobuf v1.5.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/gofuzz v1.2.0 // indirect
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
 	github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
 	github.com/gorilla/mux v1.8.0 // 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/crypto v0.0.0-20220214200702-86341886e292 // indirect
 	golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
 	golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // 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/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // 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/grpc v1.45.0 // indirect
 	google.golang.org/protobuf v1.27.1 // indirect
 	google.golang.org/protobuf v1.27.1 // indirect
 	gopkg.in/inf.v0 v0.9.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
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 	k8s.io/apimachinery v0.24.1 // indirect; see replace for the actual version used
 	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
 	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.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
 github.com/Microsoft/hcsshim v0.8.23/go.mod h1:4zegtUJth7lAvFyc6cH2gGQ5B3OFQim01nnU2M8jKDg=
 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.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-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-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
 github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
 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/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 h1:jplQcSnvFyQlD6swiqL3BmqRnhbnS+lc/EKdBLH9E80=
 github.com/cnabio/cnab-go v0.23.4/go.mod h1:9EmgHR51LFqQStzaC+xHPJlkD4OPsF6Ev5Y8e/YHEns=
 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-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-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/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/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/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.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-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-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
 github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
 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.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c=
 github.com/containerd/containerd v1.5.8/go.mod h1:YdFSv5bTFLpG2HIYmfqDpSYYTDX+mc5qtSuYx1YUb/s=
 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.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-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-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/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-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.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.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.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-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-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
 github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
 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/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.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
 github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
 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-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/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 h1:dsd3F0hhmUydFX/KFrvbK81JvlTA4T3Iy0lwDJt4PsU=
 github.com/docker/buildx v0.8.2/go.mod h1:5sMOfNwOmO2jy/MxBL4ySk2LoLIG1tQFu2EU8wbKa34=
 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 h1:RWXvuBczWuSIMjI69AnkNklNNVX2gmS0X+15AttGDVk=
 github.com/docker/cli v20.10.3-0.20220309205733-2b52f62e9627+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
 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.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 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.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=
 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.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
 github.com/gofrs/flock v0.8.0 h1:MSdYClljsF3PbENUUEx85nkWfJSGfzYI9yEBZOJz6CY=
 github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
 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 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.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
 github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
 github.com/gogo/googleapis v1.3.2/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
 github.com/gogo/googleapis v1.4.0/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.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.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.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.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.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.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4=
 github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0=
 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/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/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.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.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 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
 github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
 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/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.0/go.mod h1:FVQFLDRWwyBjDTBNQXDlWnSFREqOo3OKX9aqhmeoo74=
 github.com/moby/sys/mount v0.1.1/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/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.0/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
 github.com/moby/sys/mountinfo v0.1.3/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/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-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
 github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/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/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/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
 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.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
 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.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.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 v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
 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=
 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-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-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-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-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-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-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-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-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-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-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-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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/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-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-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-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=
 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/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=
 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
 // StartOptions group options of the Start API
 type StartOptions struct {
 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
 	Project *types.Project
 	// Attach to container and forward logs if not nil
 	// Attach to container and forward logs if not nil
 	Attach LogConsumer
 	Attach LogConsumer
@@ -133,6 +133,8 @@ type StartOptions struct {
 
 
 // RestartOptions group options of the Restart API
 // RestartOptions group options of the Restart API
 type RestartOptions struct {
 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 override container restart timeout
 	Timeout *time.Duration
 	Timeout *time.Duration
 	// Services passed in the command line to be restarted
 	// Services passed in the command line to be restarted
@@ -141,6 +143,8 @@ type RestartOptions struct {
 
 
 // StopOptions group options of the Stop API
 // StopOptions group options of the Stop API
 type StopOptions struct {
 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 override container stop timeout
 	Timeout *time.Duration
 	Timeout *time.Duration
 	// Services passed in the command line to be stopped
 	// Services passed in the command line to be stopped
@@ -201,6 +205,8 @@ type KillOptions struct {
 
 
 // RemoveOptions group options of the Remove API
 // RemoveOptions group options of the Remove API
 type RemoveOptions struct {
 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 just list removable resources
 	DryRun bool
 	DryRun bool
 	// Volumes remove anonymous volumes
 	// Volumes remove anonymous volumes
@@ -213,6 +219,8 @@ type RemoveOptions struct {
 
 
 // RunOptions group options of the Run API
 // RunOptions group options of the Run API
 type RunOptions struct {
 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
 	Name              string
 	Service           string
 	Service           string
 	Command           []string
 	Command           []string
@@ -272,6 +280,7 @@ type ListOptions struct {
 
 
 // PsOptions group options of the Ps API
 // PsOptions group options of the Ps API
 type PsOptions struct {
 type PsOptions struct {
+	Project  *types.Project
 	All      bool
 	All      bool
 	Services []string
 	Services []string
 }
 }
@@ -377,6 +386,8 @@ type LogOptions struct {
 type PauseOptions struct {
 type PauseOptions struct {
 	// Services passed in the command line to be started
 	// Services passed in the command line to be started
 	Services []string
 	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 (
 const (
@@ -445,3 +456,15 @@ const (
 	// UserCancel user cancelled compose up, we are stopping containers
 	// UserCancel user cancelled compose up, we are stopping containers
 	UserCancel
 	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 (
 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
 	// This will be used by VSCode to detect when creating context if the user needs to login first
 	ExitCodeLoginRequired = 5
 	ExitCodeLoginRequired = 5
 )
 )

+ 2 - 2
pkg/compose/attach.go

@@ -127,9 +127,9 @@ func (s *composeService) attachContainerStreams(ctx context.Context, container s
 	if stdout != nil {
 	if stdout != nil {
 		go func() {
 		go func() {
 			if tty {
 			if tty {
-				io.Copy(stdout, streamOut) // nolint:errcheck
+				io.Copy(stdout, streamOut) //nolint:errcheck
 			} else {
 			} 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 {
 func (s *composeService) build(ctx context.Context, project *types.Project, options api.BuildOptions) error {
 	opts := map[string]build.Options{}
 	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...)
 	services, err := project.GetServices(options.Services...)
 	if err != nil {
 	if err != nil {
@@ -61,29 +58,30 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
 	}
 	}
 
 
 	for _, service := range services {
 	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)
 	_, 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
 	// set digest as com.docker.compose.image label so we can detect outdated containers
 	for i, service := range project.Services {
 	for i, service := range project.Services {
-		image := getImageName(service, project.Name)
+		image := api.GetImageNameOrDefault(service, project.Name)
 		digest, ok := images[image]
 		digest, ok := images[image]
 		if ok {
 		if ok {
 			if project.Services[i].Labels == nil {
 			if project.Services[i].Labels == nil {
 				project.Services[i].Labels = types.Labels{}
 				project.Services[i].Labels = types.Labels{}
 			}
 			}
 			project.Services[i].CustomLabels[api.ImageDigestLabel] = digest
 			project.Services[i].CustomLabels[api.ImageDigestLabel] = digest
-			project.Services[i].Image = image
 		}
 		}
 	}
 	}
 	return nil
 	return nil
@@ -153,7 +150,7 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
 		if service.Image == "" && service.Build == nil {
 		if service.Image == "" && service.Build == nil {
 			return nil, fmt.Errorf("invalid service %q. Must specify either image or build", service.Name)
 			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]
 		_, localImagePresent := images[imageName]
 
 
 		if service.Build != nil {
 		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) {
 func (s *composeService) getLocalImagesDigests(ctx context.Context, project *types.Project) (map[string]string, error) {
-	imageNames := []string{}
+	var imageNames []string
 	for _, s := range project.Services {
 	for _, s := range project.Services {
-		imgName := getImageName(s, project.Name)
+		imgName := api.GetImageNameOrDefault(s, project.Name)
 		if !utils.StringContains(imageNames, imgName) {
 		if !utils.StringContains(imageNames, imgName) {
 			imageNames = append(imageNames, imgName)
 			imageNames = append(imageNames, imgName)
 		}
 		}
@@ -189,11 +186,11 @@ func (s *composeService) getLocalImagesDigests(ctx context.Context, project *typ
 		images[name] = info.ID
 		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]
 		digest, ok := images[imgName]
 		if ok {
 		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
 	var tags []string
 	tags = append(tags, imageTag)
 	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
 	var plats []specs.Platform
 	if platform, ok := project.Environment["DOCKER_DEFAULT_PLATFORM"]; ok {
 	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 {
 	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 {
 		if err != nil {
 			return build.Options{}, err
 			return build.Options{}, err
 		}
 		}
-		p := secretsprovider.NewSecretProvider(store)
-		sessionConfig = append(sessionConfig, p)
+		sessionConfig = append(sessionConfig, secretsProvider)
 	}
 	}
 
 
 	if len(service.Build.Tags) > 0 {
 	if len(service.Build.Tags) > 0 {
@@ -324,11 +306,11 @@ func mergeArgs(m ...types.Mapping) types.Mapping {
 	return merged
 	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 dockerfile
 	}
 	}
-	return filepath.Join(context, dockerfile)
+	return filepath.Join(ctxName, dockerfile)
 }
 }
 
 
 func sshAgentProvider(sshKeys types.SSHConfig) (session.Attachable, error) {
 func sshAgentProvider(sshKeys types.SSHConfig) (session.Attachable, error) {
@@ -341,3 +323,30 @@ func sshAgentProvider(sshKeys types.SSHConfig) (session.Attachable, error) {
 	}
 	}
 	return sshprovider.NewSSHAgentProvider(sshConfig)
 	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"
 	"github.com/compose-spec/compose-go/types"
 	buildx "github.com/docker/buildx/build"
 	buildx "github.com/docker/buildx/build"
 	"github.com/docker/cli/cli/command/image/build"
 	"github.com/docker/cli/cli/command/image/build"
+	"github.com/docker/compose/v2/pkg/api"
 	dockertypes "github.com/docker/docker/api/types"
 	dockertypes "github.com/docker/docker/api/types"
 	"github.com/docker/docker/cli"
 	"github.com/docker/docker/cli"
 	"github.com/docker/docker/pkg/archive"
 	"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 nameDigests = make(map[string]string)
 	var errs error
 	var errs error
 	err := project.WithServices(nil, func(service types.ServiceConfig) 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]
 		o, ok := opts[imageName]
 		if !ok {
 		if !ok {
 			return nil
 			return nil
@@ -64,7 +65,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
 	return nameDigests, errs
 	return nameDigests, errs
 }
 }
 
 
-// nolint: gocyclo
+//nolint: gocyclo
 func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options buildx.Options) (string, error) {
 func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options buildx.Options) (string, error) {
 	var (
 	var (
 		buildCtx      io.ReadCloser
 		buildCtx      io.ReadCloser
@@ -96,7 +97,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
 			if err != nil {
 			if err != nil {
 				return "", errors.Errorf("unable to open Dockerfile: %v", err)
 				return "", errors.Errorf("unable to open Dockerfile: %v", err)
 			}
 			}
-			defer dockerfileCtx.Close() // nolint:errcheck
+			defer dockerfileCtx.Close() //nolint:errcheck
 		}
 		}
 	case urlutil.IsGitURL(specifiedContext):
 	case urlutil.IsGitURL(specifiedContext):
 		tempDir, relDockerfile, err = build.GetContextFromGitURL(specifiedContext, dockerfileName)
 		tempDir, relDockerfile, err = build.GetContextFromGitURL(specifiedContext, dockerfileName)
@@ -111,7 +112,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
 	}
 	}
 
 
 	if tempDir != "" {
 	if tempDir != "" {
-		defer os.RemoveAll(tempDir) // nolint:errcheck
+		defer os.RemoveAll(tempDir) //nolint:errcheck
 		contextDir = tempDir
 		contextDir = tempDir
 	}
 	}
 
 
@@ -175,7 +176,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
 	if err != nil {
 	if err != nil {
 		return "", err
 		return "", err
 	}
 	}
-	defer response.Body.Close() // nolint:errcheck
+	defer response.Body.Close() //nolint:errcheck
 
 
 	imageID := ""
 	imageID := ""
 	aux := func(msg jsonmessage.JSONMessage) {
 	aux := func(msg jsonmessage.JSONMessage) {
@@ -214,7 +215,7 @@ func (s *composeService) doBuildClassicSimpleImage(ctx context.Context, options
 		if imageID == "" {
 		if imageID == "" {
 			return "", errors.Errorf("Server did not provide an image ID. Cannot write %s", options.ImageIDFile)
 			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
 			return "", err
 		}
 		}
 	}
 	}

+ 2 - 24
pkg/compose/compose.go

@@ -24,6 +24,8 @@ import (
 	"io"
 	"io"
 	"strings"
 	"strings"
 
 
+	"gopkg.in/yaml.v2"
+
 	"github.com/compose-spec/compose-go/types"
 	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/cli/cli/config/configfile"
 	"github.com/docker/cli/cli/config/configfile"
@@ -33,12 +35,8 @@ import (
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/client"
 	"github.com/docker/docker/client"
 	"github.com/pkg/errors"
 	"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
 // NewComposeService create a local implementation of the compose.Service API
 func NewComposeService(dockerCli command.Cli) api.Service {
 func NewComposeService(dockerCli command.Cli) api.Service {
 	return &composeService{
 	return &composeService{
@@ -175,26 +173,6 @@ SERVICES:
 	return project, nil
 	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) {
 func (s *composeService) actualVolumes(ctx context.Context, projectName string) (types.Volumes, error) {
 	volumes, err := s.apiClient().VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
 	volumes, err := s.apiClient().VolumeList(ctx, filters.NewArgs(projectFilter(projectName)))
 	if err != nil {
 	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 {
 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 != "" {
 	if service.ContainerName != "" {
 		name = service.ContainerName
 		name = service.ContainerName
 	}
 	}
@@ -553,8 +553,8 @@ func (s composeService) getLinks(ctx context.Context, projectName string, servic
 			containerName := getCanonicalContainerName(c)
 			containerName := getCanonicalContainerName(c)
 			links = append(links,
 			links = append(links,
 				format(containerName, linkName),
 				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)
 			containerName := getCanonicalContainerName(c)
 			links = append(links,
 			links = append(links,
 				format(containerName, service.Name),
 				format(containerName, service.Name),
-				format(containerName, strings.TrimPrefix(containerName, projectName+Separator)),
+				format(containerName, strings.TrimPrefix(containerName, projectName+api.Separator)),
 				format(containerName, containerName),
 				format(containerName, containerName),
 			)
 			)
 		}
 		}
@@ -605,8 +605,9 @@ func (s *composeService) connectContainerToNetwork(ctx context.Context, id strin
 		ipv4Address = cfg.Ipv4Address
 		ipv4Address = cfg.Ipv4Address
 		ipv6Address = cfg.Ipv6Address
 		ipv6Address = cfg.Ipv6Address
 		ipam = &network.EndpointIPAMConfig{
 		ipam = &network.EndpointIPAMConfig{
-			IPv4Address: ipv4Address,
-			IPv6Address: ipv6Address,
+			IPv4Address:  ipv4Address,
+			IPv6Address:  ipv6Address,
+			LinkLocalIPs: cfg.LinkLocalIPs,
 		}
 		}
 	}
 	}
 	err := s.apiClient().NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{
 	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
 	preArchive := content
-	if len(srcInfo.RebaseName) != 0 {
+	if srcInfo.RebaseName != "" {
 		_, srcBase := archive.SplitPathDirEntry(srcInfo.Path)
 		_, srcBase := archive.SplitPathDirEntry(srcInfo.Path)
 		preArchive = archive.RebaseArchiveEntries(content, srcBase, srcInfo.RebaseName)
 		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
 	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,
 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) {
 	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,
 		AttachStderr:    true,
 		AttachStdout:    true,
 		AttachStdout:    true,
 		Cmd:             runCmd,
 		Cmd:             runCmd,
-		Image:           getImageName(service, p.Name),
+		Image:           api.GetImageNameOrDefault(service, p.Name),
 		WorkingDir:      service.WorkingDir,
 		WorkingDir:      service.WorkingDir,
 		Entrypoint:      entrypoint,
 		Entrypoint:      entrypoint,
 		NetworkDisabled: service.NetworkMode == "disabled",
 		NetworkDisabled: service.NetworkMode == "disabled",
@@ -314,8 +306,9 @@ func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project,
 			ipv4Address = config.Ipv4Address
 			ipv4Address = config.Ipv4Address
 			ipv6Address = config.Ipv6Address
 			ipv6Address = config.Ipv6Address
 			ipam = &network.EndpointIPAMConfig{
 			ipam = &network.EndpointIPAMConfig{
-				IPv4Address: ipv4Address,
-				IPv6Address: ipv6Address,
+				IPv4Address:  ipv4Address,
+				IPv6Address:  ipv6Address,
+				LinkLocalIPs: config.LinkLocalIPs,
 			}
 			}
 		}
 		}
 		networkConfig = &network.NetworkingConfig{
 		networkConfig = &network.NetworkingConfig{
@@ -680,7 +673,7 @@ func getVolumesFrom(project *types.Project, volumesFrom []string) ([]string, []s
 			continue
 			continue
 		}
 		}
 		if spec[0] == "container" {
 		if spec[0] == "container" {
-			volumes = append(volumes, strings.Join(spec[1:], ":"))
+			volumes = append(volumes, vol)
 			continue
 			continue
 		}
 		}
 		serviceName := spec[0]
 		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) {
 	inherit *moby.Container) (map[string]struct{}, []string, []mount.Mount, error) {
 	var mounts = []mount.Mount{}
 	var mounts = []mount.Mount{}
 
 
-	image := getImageName(service, p.Name)
+	image := api.GetImageNameOrDefault(service, p.Name)
 	imgInspect, _, err := s.apiClient().ImageInspectWithRaw(ctx, image)
 	imgInspect, _, err := s.apiClient().ImageInspectWithRaw(ctx, image)
 	if err != nil {
 	if err != nil {
 		return nil, nil, nil, err
 		return nil, nil, nil, err
@@ -727,8 +720,12 @@ func (s *composeService) buildContainerVolumes(ctx context.Context, p types.Proj
 	binds := []string{}
 	binds := []string{}
 MOUNTS:
 MOUNTS:
 	for _, m := range mountOptions {
 	for _, m := range mountOptions {
+		if m.Type == mount.TypeNamedPipe {
+			mounts = append(mounts, m)
+			continue
+		}
 		volumeMounts[m.Target] = struct{}{}
 		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
 			// `Mount` is preferred but does not offer option to created host path if missing
 			// so `Bind` API is used here with raw volume string
 			// so `Bind` API is used here with raw volume string
 			// see https://github.com/moby/moby/issues/43483
 			// see https://github.com/moby/moby/issues/43483
@@ -893,7 +890,7 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 			continue
 			continue
 		}
 		}
 
 
-		mount, err := buildMount(p, types.ServiceVolumeConfig{
+		mnt, err := buildMount(p, types.ServiceVolumeConfig{
 			Type:     types.VolumeTypeBind,
 			Type:     types.VolumeTypeBind,
 			Source:   definedSecret.File,
 			Source:   definedSecret.File,
 			Target:   target,
 			Target:   target,
@@ -902,7 +899,7 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
-		mounts[target] = mount
+		mounts[target] = mnt
 	}
 	}
 	values := make([]mount.Mount, 0, len(mounts))
 	values := make([]mount.Mount, 0, len(mounts))
 	for _, v := range mounts {
 	for _, v := range mounts {
@@ -911,8 +908,8 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 	return values, nil
 	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) {
 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 {
 	if err != nil {
 		return err
 		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.External.External {
 			if n.Driver == "overlay" {
 			if n.Driver == "overlay" {
 				// Swarm nodes do not register overlay networks that were
 				// Swarm nodes do not register overlay networks that were

+ 29 - 9
pkg/compose/create_test.go

@@ -22,11 +22,12 @@ import (
 	"sort"
 	"sort"
 	"testing"
 	"testing"
 
 
-	"github.com/compose-spec/compose-go/types"
-	composetypes "github.com/compose-spec/compose-go/types"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/api"
+
+	composetypes "github.com/compose-spec/compose-go/types"
 	moby "github.com/docker/docker/api/types"
 	moby "github.com/docker/docker/api/types"
 	mountTypes "github.com/docker/docker/api/types/mount"
 	mountTypes "github.com/docker/docker/api/types/mount"
+
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert"
 )
 )
 
 
@@ -45,6 +46,18 @@ func TestBuildBindMount(t *testing.T) {
 	assert.Equal(t, mount.Type, mountTypes.TypeBind)
 	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) {
 func TestBuildVolumeMount(t *testing.T) {
 	project := composetypes.Project{
 	project := composetypes.Project{
 		Name: "myProject",
 		Name: "myProject",
@@ -66,17 +79,17 @@ func TestBuildVolumeMount(t *testing.T) {
 }
 }
 
 
 func TestServiceImageName(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) {
 func TestPrepareNetworkLabels(t *testing.T) {
-	project := types.Project{
+	project := composetypes.Project{
 		Name:     "myProject",
 		Name:     "myProject",
-		Networks: types.Networks(map[string]types.NetworkConfig{"skynet": {}}),
+		Networks: composetypes.Networks(map[string]composetypes.NetworkConfig{"skynet": {}}),
 	}
 	}
 	prepareNetworks(&project)
 	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.network": "skynet",
 		"com.docker.compose.project": "myProject",
 		"com.docker.compose.project": "myProject",
 		"com.docker.compose.version": api.ComposeVersion,
 		"com.docker.compose.version": api.ComposeVersion,
@@ -98,6 +111,11 @@ func TestBuildContainerMountOptions(t *testing.T) {
 						Type:   composetypes.VolumeTypeVolume,
 						Type:   composetypes.VolumeTypeVolume,
 						Target: "/var/myvolume2",
 						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
 		return mounts[i].Target < mounts[j].Target
 	})
 	})
 	assert.NilError(t, err)
 	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[0].Target, "/var/myvolume1")
 	assert.Equal(t, mounts[1].Target, "/var/myvolume2")
 	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)
 	mounts, err = buildContainerMountOptions(project, project.Services[0], moby.ImageInspect{}, inherit)
 	sort.Slice(mounts, func(i, j int) bool {
 	sort.Slice(mounts, func(i, j int) bool {
 		return mounts[i].Target < mounts[j].Target
 		return mounts[i].Target < mounts[j].Target
 	})
 	})
 	assert.NilError(t, err)
 	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[0].Target, "/var/myvolume1")
 	assert.Equal(t, mounts[1].Target, "/var/myvolume2")
 	assert.Equal(t, mounts[1].Target, "/var/myvolume2")
+	assert.Equal(t, mounts[2].Target, "\\\\.\\pipe\\docker_engine")
 }
 }
 
 
 func TestGetDefaultNetworkMode(t *testing.T) {
 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)
 	w := progress.ContextWriter(ctx)
 	resourceToRemove := false
 	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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
@@ -163,14 +166,16 @@ func (s *composeService) removeNetwork(ctx context.Context, name string, w progr
 
 
 	var removed int
 	var removed int
 	for _, net := range networks {
 	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 {
 	if removed == 0 {
@@ -193,7 +198,7 @@ func (s *composeService) getServiceImages(options api.DownOptions, project *type
 			continue
 			continue
 		}
 		}
 		if image == "" {
 		if image == "" {
-			image = getImageName(service, project.Name)
+			image = api.GetImageNameOrDefault(service, project.Name)
 		}
 		}
 		images[image] = struct{}{}
 		images[image] = struct{}{}
 	}
 	}

+ 3 - 3
pkg/compose/down_test.go

@@ -40,7 +40,7 @@ func TestDown(t *testing.T) {
 	tested.dockerCli = cli
 	tested.dockerCli = cli
 	cli.EXPECT().Client().Return(api).AnyTimes()
 	cli.EXPECT().Client().Return(api).AnyTimes()
 
 
-	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
+	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
 		[]moby.Container{
 		[]moby.Container{
 			testContainer("service1", "123", false),
 			testContainer("service1", "123", false),
 			testContainer("service2", "456", false),
 			testContainer("service2", "456", false),
@@ -88,7 +88,7 @@ func TestDownRemoveOrphans(t *testing.T) {
 	tested.dockerCli = cli
 	tested.dockerCli = cli
 	cli.EXPECT().Client().Return(api).AnyTimes()
 	cli.EXPECT().Client().Return(api).AnyTimes()
 
 
-	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
+	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(true)).Return(
 		[]moby.Container{
 		[]moby.Container{
 			testContainer("service1", "123", false),
 			testContainer("service1", "123", false),
 			testContainer("service2", "789", false),
 			testContainer("service2", "789", false),
@@ -125,7 +125,7 @@ func TestDownRemoveVolumes(t *testing.T) {
 	tested.dockerCli = cli
 	tested.dockerCli = cli
 	cli.EXPECT().Client().Return(api).AnyTimes()
 	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)
 		[]moby.Container{testContainer("service1", "123", false)}, nil)
 	api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
 	api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))).
 		Return(volume.VolumeListOKBody{
 		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"
 	"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) {
 func ServiceHash(o types.ServiceConfig) (string, error) {
 	// remove the Build config when generating the service hash
 	// remove the Build config when generating the service hash
 	o.Build = nil
 	o.Build = nil

+ 9 - 2
pkg/compose/kill_test.go

@@ -18,6 +18,7 @@ package compose
 
 
 import (
 import (
 	"context"
 	"context"
+	"fmt"
 	"path/filepath"
 	"path/filepath"
 	"strings"
 	"strings"
 	"testing"
 	"testing"
@@ -110,9 +111,15 @@ func anyCancellableContext() gomock.Matcher {
 	return gomock.AssignableToTypeOf(ctxWithCancel)
 	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{
 	return moby.ContainerListOptions{
-		Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
+		Filters: filter,
 		All:     true,
 		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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
-	defer r.Close() // nolint errcheck
+	defer r.Close() //nolint errcheck
 
 
 	name := getContainerNameWithoutProject(c)
 	name := getContainerNameWithoutProject(c)
 	w := utils.GetWriter(func(line string) {
 	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 {
 	for _, status := range keys {
 		nb := nbByStatus[status]
 		nb := nbByStatus[status]
 		if result != "" {
 		if result != "" {
-			result = result + ", "
+			result += ", "
 		}
 		}
-		result = result + fmt.Sprintf("%s(%d)", status, nb)
+		result += fmt.Sprintf("%s(%d)", status, nb)
 	}
 	}
 	return result
 	return result
 }
 }

+ 2 - 2
pkg/compose/metrics.go

@@ -50,13 +50,13 @@ var (
 	ComposeParseFailure = FailureCategory{MetricsStatus: ComposeParseFailureStatus, ExitCode: 15}
 	ComposeParseFailure = FailureCategory{MetricsStatus: ComposeParseFailureStatus, ExitCode: 15}
 	// CommandSyntaxFailure failure for command line syntax
 	// CommandSyntaxFailure failure for command line syntax
 	CommandSyntaxFailure = FailureCategory{MetricsStatus: CommandSyntaxFailureStatus, ExitCode: 16}
 	CommandSyntaxFailure = FailureCategory{MetricsStatus: CommandSyntaxFailureStatus, ExitCode: 16}
-	//BuildFailure failure while building images.
+	// BuildFailure failure while building images.
 	BuildFailure = FailureCategory{MetricsStatus: BuildFailureStatus, ExitCode: 17}
 	BuildFailure = FailureCategory{MetricsStatus: BuildFailureStatus, ExitCode: 17}
 	// PullFailure failure while pulling image
 	// PullFailure failure while pulling image
 	PullFailure = FailureCategory{MetricsStatus: PullFailureStatus, ExitCode: 18}
 	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 {
 func ByExitCode(exitCode int) FailureCategory {
 	switch exitCode {
 	switch exitCode {
 	case 0:
 	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 {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
+	if options.Project != nil {
+		containers = containers.filter(isService(options.Project.ServiceNames()...))
+	}
+
 	w := progress.ContextWriter(ctx)
 	w := progress.ContextWriter(ctx)
 	eg, ctx := errgroup.WithContext(ctx)
 	eg, ctx := errgroup.WithContext(ctx)
 	containers.forEach(func(container moby.Container) {
 	containers.forEach(func(container moby.Container) {
@@ -67,6 +71,10 @@ func (s *composeService) unPause(ctx context.Context, projectName string, option
 		return err
 		return err
 	}
 	}
 
 
+	if options.Project != nil {
+		containers = containers.filter(isService(options.Project.ServiceNames()...))
+	}
+
 	w := progress.ContextWriter(ctx)
 	w := progress.ContextWriter(ctx)
 	eg, ctx := errgroup.WithContext(ctx)
 	eg, ctx := errgroup.WithContext(ctx)
 	containers.forEach(func(container moby.Container) {
 	containers.forEach(func(container moby.Container) {

+ 5 - 5
pkg/compose/printer.go

@@ -32,6 +32,11 @@ type logPrinter interface {
 	Cancel()
 	Cancel()
 }
 }
 
 
+type printer struct {
+	queue    chan api.ContainerEvent
+	consumer api.LogConsumer
+}
+
 // newLogPrinter builds a LogPrinter passing containers logs to LogConsumer
 // newLogPrinter builds a LogPrinter passing containers logs to LogConsumer
 func newLogPrinter(consumer api.LogConsumer) logPrinter {
 func newLogPrinter(consumer api.LogConsumer) logPrinter {
 	queue := make(chan api.ContainerEvent)
 	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) {
 func (p *printer) HandleEvent(event api.ContainerEvent) {
 	p.queue <- event
 	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
 		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))
 	summary := make([]api.ContainerSummary, len(containers))
 	eg, ctx := errgroup.WithContext(ctx)
 	eg, ctx := errgroup.WithContext(ctx)
 	for i, container := range containers {
 	for i, container := range containers {

+ 3 - 0
pkg/compose/ps_test.go

@@ -26,6 +26,7 @@ import (
 
 
 	moby "github.com/docker/docker/api/types"
 	moby "github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/filters"
+	"github.com/docker/docker/api/types/volume"
 
 
 	compose "github.com/docker/compose/v2/pkg/api"
 	compose "github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/mocks"
 	"github.com/docker/compose/v2/pkg/mocks"
@@ -48,6 +49,8 @@ func TestPs(t *testing.T) {
 	c2, inspect2 := containerDetails("service1", "456", "running", "", 0)
 	c2, inspect2 := containerDetails("service1", "456", "running", "", 0)
 	c2.Ports = []moby.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}}
 	c2.Ports = []moby.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}}
 	c3, inspect3 := containerDetails("service2", "789", "exited", "", 130)
 	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().ContainerList(ctx, listOpts).Return([]moby.Container{c1, c2, c3}, nil)
 	api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil)
 	api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil)
 	api.EXPECT().ContainerInspect(anyCancellableContext(), "456").Return(inspect2, 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 {
 func (s *composeService) Remove(ctx context.Context, projectName string, options api.RemoveOptions) error {
 	projectName = strings.ToLower(projectName)
 	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 err != nil {
 		if api.IsNotFoundError(err) {
 		if api.IsNotFoundError(err) {
 			fmt.Fprintln(s.stderr(), "No stopped containers")
 			fmt.Fprintln(s.stderr(), "No stopped containers")
@@ -40,6 +40,10 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options
 		return err
 		return err
 	}
 	}
 
 
+	if options.Project != nil {
+		containers = containers.filter(isService(options.Project.ServiceNames()...))
+	}
+
 	stoppedContainers := containers.filter(func(c moby.Container) bool {
 	stoppedContainers := containers.filter(func(c moby.Container) bool {
 		return c.State != ContainerRunning
 		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 {
 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 {
 	if err != nil {
 		return err
 		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 {
 	if len(options.Services) == 0 {
@@ -50,12 +52,12 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
 	}
 	}
 
 
 	w := progress.ContextWriter(ctx)
 	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) {
 		if !utils.StringContains(options.Services, service) {
 			return nil
 			return nil
 		}
 		}
 		eg, ctx := errgroup.WithContext(ctx)
 		eg, ctx := errgroup.WithContext(ctx)
-		for _, container := range observedState.filter(isService(service)) {
+		for _, container := range containers.filter(isService(service)) {
 			container := container
 			container := container
 			eg.Go(func() error {
 			eg.Go(func() error {
 				eventName := getContainerProgressName(container)
 				eventName := getContainerProgressName(container)
@@ -69,8 +71,4 @@ func (s *composeService) restart(ctx context.Context, projectName string, option
 		}
 		}
 		return eg.Wait()
 		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
 		service.Entrypoint = opts.Entrypoint
 	}
 	}
 	if len(opts.Environment) > 0 {
 	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
 			return v, ok
 		}).RemoveEmpty()
 		}).RemoveEmpty()
-		service.Environment.OverrideBy(projectEnv)
+		service.Environment.OverrideBy(serviceOverrideEnv)
 	}
 	}
 	for k, v := range opts.Labels {
 	for k, v := range opts.Labels {
 		service.Labels = service.Labels.Add(k, v)
 		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)
 	value := []byte(env)
 	b := bytes.Buffer{}
 	b := bytes.Buffer{}
 	tarWriter := tar.NewWriter(&b)
 	tarWriter := tar.NewWriter(&b)
-	mode := uint32(0400)
+	mode := uint32(0o400)
 	if config.Mode != nil {
 	if config.Mode != nil {
 		mode = *config.Mode
 		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/api"
 	"github.com/docker/compose/v2/pkg/progress"
 	"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 {
 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 {
 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 {
 	if err != nil {
 		return err
 		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 {
 	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"
 	"github.com/docker/compose/v2/pkg/mocks"
 
 
 	moby "github.com/docker/docker/api/types"
 	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"
 	"github.com/golang/mock/gomock"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/assert"
 )
 )
@@ -40,12 +42,16 @@ func TestStopTimeout(t *testing.T) {
 	cli.EXPECT().Client().Return(api).AnyTimes()
 	cli.EXPECT().Client().Return(api).AnyTimes()
 
 
 	ctx := context.Background()
 	ctx := context.Background()
-	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return(
+	api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return(
 		[]moby.Container{
 		[]moby.Container{
 			testContainer("service1", "123", false),
 			testContainer("service1", "123", false),
 			testContainer("service1", "456", false),
 			testContainer("service1", "456", false),
 			testContainer("service2", "789", false),
 			testContainer("service2", "789", false),
 		}, nil)
 		}, 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
 	timeout := time.Duration(2) * time.Second
 	api.EXPECT().ContainerStop(gomock.Any(), "123", &timeout).Return(nil)
 	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 {
 		return progress.Run(ctx, func(ctx context.Context) error {
 			go func() {
 			go func() {
 				<-signalChan
 				<-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{
 			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
 		<-signalChan
 		printer.Cancel()
 		printer.Cancel()
 		fmt.Println("Gracefully stopping... (press Ctrl+C again to force)")
 		fmt.Println("Gracefully stopping... (press Ctrl+C again to force)")
-		stopFunc() // nolint:errcheck
+		stopFunc() //nolint:errcheck
 	}()
 	}()
 
 
 	var exitCode int
 	var exitCode int

部分文件因文件數量過多而無法顯示