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

This commit is contained in:
Vedant Koditkar 2022-08-06 17:58:10 +05:30
commit e623b5ca1e
127 changed files with 3001 additions and 2385 deletions

View File

@ -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

View File

@ -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 go-version: ${{ env.GO_VERSION }}
key: go-${{ hashFiles('**/go.sum') }} 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 - name: Checkout code into the Go module directory
uses: actions/setup-go@v2 uses: actions/checkout@v3
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v3
with: with:
go-version: 1.18.3 go-version: ${{ env.GO_VERSION }}
id: go 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 - name: Checkout code into the Go module directory
uses: actions/setup-go@v2 uses: actions/checkout@v3
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v3
with: with:
go-version: 1.18.3 go-version: ${{ env.GO_VERSION }}
id: go 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 - name: Checkout code into the Go module directory
uses: actions/setup-go@v2 uses: actions/checkout@v3
- name: Set up Go ${{ env.GO_VERSION }}
uses: actions/setup-go@v3
with: with:
go-version: 1.18.3 go-version: ${{ env.GO_VERSION }}
id: go 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

View File

@ -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:

View File

@ -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

View File

@ -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 it! Take a look at existing tests for inspiration. Also end-to-end tests are
suite](README.md) on your branch before available. Run the full test suite, both unit tests and e2e tests on your
submitting a pull request. 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

View File

@ -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 GO_VERSION=1.18.5-alpine
ARG GOLANGCI_LINT_VERSION=v1.40.1-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

View File

@ -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

View File

@ -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 != "" {

View File

@ -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) c.Flags().SetInterspersed(false)
opts.addProjectFlags(command.Flags()) opts.addProjectFlags(c.Flags())
command.Flags().StringVar(&ansi, "ansi", "auto", `Control when to print ANSI control characters ("never"|"always"|"auto")`) c.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") c.Flags().BoolVarP(&version, "version", "v", false, "Show the Docker Compose version information")
command.Flags().MarkHidden("version") //nolint:errcheck c.Flags().MarkHidden("version") //nolint:errcheck
command.Flags().BoolVar(&noAnsi, "no-ansi", false, `Do not print ANSI control characters (DEPRECATED)`) c.Flags().BoolVar(&noAnsi, "no-ansi", false, `Do not print ANSI control characters (DEPRECATED)`)
command.Flags().MarkHidden("no-ansi") //nolint:errcheck c.Flags().MarkHidden("no-ansi") //nolint:errcheck
command.Flags().BoolVar(&verbose, "verbose", false, "Show more output") c.Flags().BoolVar(&verbose, "verbose", false, "Show more output")
command.Flags().MarkHidden("verbose") //nolint:errcheck c.Flags().MarkHidden("verbose") //nolint:errcheck
return command 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 { // overwrite the process env with merged OS + env file results
if err = os.Setenv(k, v); err != nil { return err
return err
}
} }
} }
return nil return nil

View File

@ -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 {

View File

@ -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
} }
} }

View File

@ -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 { if name == "volume" {
case "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 project, name, err := opts.projectOrName()
var project *types.Project if err != nil {
if opts.ProjectName == "" { return err
p, err := opts.toProject(nil)
if err != nil {
return err
}
project = p
name = p.Name
} }
var timeout *time.Duration var timeout *time.Duration

View File

@ -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 {

View File

@ -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 {

View File

@ -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)

View File

@ -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,
}) })

View File

@ -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().StringVar(&lsOpts.Format, "format", "pretty", "Format the output. Values: [pretty | json].")
lsCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Only display IDs.") lsCmd.Flags().BoolVarP(&lsOpts.Quiet, "quiet", "q", false, "Only display IDs.")
lsCmd.Flags().Var(&opts.Filter, "filter", "Filter output based on conditions provided.") lsCmd.Flags().Var(&lsOpts.Filter, "filter", "Filter output based on conditions provided.")
lsCmd.Flags().BoolVarP(&opts.All, "all", "a", false, "Show all stopped Compose projects") 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 { func runList(ctx context.Context, backend api.Service, lsOpts lsOptions) error {
filters := opts.Filter.Value() 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)
} }

View File

@ -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)

View File

@ -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,
}) })
} }

View File

@ -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 {

View File

@ -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,
}) })

View File

@ -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 {

View File

@ -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)

View File

@ -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,
}) })
} }

View File

@ -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", Use: "restart [OPTIONS] [SERVICE...]",
Short: "Restart containers", 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,
}) })
} }

View File

@ -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")

View File

@ -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,
}) })
} }

View File

@ -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,
}) })
} }

View File

@ -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 { if s.Name != name {
service, err := project.GetService(name) continue
if err != nil {
return err
}
if service.Deploy == nil {
service.Deploy = &types.DeployConfig{}
}
service.Deploy.Replicas = &replicas
project.Services[i] = service
return nil
} }
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)
} }

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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 |

View File

@ -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

View File

@ -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-->

View File

@ -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-->

View File

@ -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
``̀` ```

View File

@ -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

View File

@ -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. |

View File

@ -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. |

View File

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

View File

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

View File

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

View File

@ -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 usage: |-
cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH" 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 - option: all
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Copy to all the containers of the service. description: Copy to all the containers of the service.
deprecated: true deprecated: true
hidden: true hidden: true
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: archive - option: archive
shorthand: a shorthand: a
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Archive mode (copy all uid/gid information) description: Archive mode (copy all uid/gid information)
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: follow-link - option: follow-link
shorthand: L shorthand: L
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Always follow symbol link in SRC_PATH description: Always follow symbol link in SRC_PATH
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: index - option: index
value_type: int value_type: int
default_value: "0" default_value: "0"
description: | description: |
Index of the container if there are multiple instances of a service . Index of the container if there are multiple instances of a service .
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 - option: build
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Build images before starting containers. description: Build images before starting containers.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: force-recreate - option: force-recreate
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: | description: |
Recreate containers even if their configuration and image haven't changed. Recreate containers even if their configuration and image haven't changed.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-build - option: no-build
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Don't build an image, even if it's missing. description: Don't build an image, even if it's missing.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-recreate - option: no-recreate
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: | description: |
If containers already exist, don't recreate them. Incompatible with --force-recreate. If containers already exist, don't recreate them. Incompatible with --force-recreate.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: 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

View File

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

View File

@ -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 ```json
{ {
"time": "2015-11-20T18:01:03.615550", "time": "2015-11-20T18:01:03.615550",
"type": "container", "type": "container",
"action": "create", "action": "create",
"id": "213cf7...5fc39a", "id": "213cf7...5fc39a",
"service": "web", "service": "web",
"attributes": { "attributes": {
"name": "application_web_1", "name": "application_web_1",
"image": "alpine:edge" "image": "alpine:edge"
} }
} }
``` ```
The events that can be received using this can be seen [here](/engine/reference/commandline/events/#object-types). The events that can be received using this can be seen [here](/engine/reference/commandline/events/#object-types).
usage: docker compose events [options] [--] [SERVICE...] usage: docker compose events [OPTIONS] [SERVICE...]
pname: docker compose pname: docker compose
plink: docker_compose.yaml plink: docker_compose.yaml
options: options:
- option: json - option: json
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Output events as a stream of json objects description: Output events as a stream of json objects
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 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. 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...] 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 - option: detach
shorthand: d shorthand: d
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: 'Detached mode: Run command in the background.' description: 'Detached mode: Run command in the background.'
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: env - option: env
shorthand: e shorthand: e
value_type: stringArray value_type: stringArray
default_value: '[]' default_value: '[]'
description: Set environment variables description: Set environment variables
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: index - option: index
value_type: int value_type: int
default_value: "1" default_value: "1"
description: | description: |
index of the container if there are multiple instances of a service [default: 1]. index of the container if there are multiple instances of a service [default: 1].
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: interactive - option: interactive
shorthand: i shorthand: i
value_type: bool value_type: bool
default_value: "true" default_value: "true"
description: Keep STDIN open even if not attached. description: Keep STDIN open even if not attached.
deprecated: false deprecated: false
hidden: true hidden: true
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-TTY - option: no-TTY
shorthand: T shorthand: T
value_type: bool value_type: bool
default_value: "true" default_value: "true"
description: | description: |
Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY. Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: privileged - option: privileged
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Give extended privileges to the process. description: Give extended privileges to the process.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: tty - option: tty
shorthand: t shorthand: t
value_type: bool value_type: bool
default_value: "true" default_value: "true"
description: Allocate a pseudo-TTY. description: Allocate a pseudo-TTY.
deprecated: false deprecated: false
hidden: true hidden: true
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: user - option: user
shorthand: u shorthand: u
value_type: string value_type: string
description: Run the command as this user. description: Run the command as this user.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: workdir - option: workdir
shorthand: w shorthand: w
value_type: string value_type: string
description: Path to workdir directory for this command. description: Path to workdir directory for this command.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 - option: quiet
shorthand: q shorthand: q
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Only display IDs description: Only display IDs
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 ```console
$ docker-compose kill -s SIGINT $ docker-compose kill -s SIGINT
``` ```
usage: docker compose kill [options] [SERVICE...] usage: docker compose kill [OPTIONS] [SERVICE...]
pname: docker compose pname: docker compose
plink: docker_compose.yaml plink: docker_compose.yaml
options: options:
- option: signal - option: signal
shorthand: s shorthand: s
value_type: string value_type: string
default_value: SIGKILL default_value: SIGKILL
description: SIGNAL to send to the container. description: SIGNAL to send to the container.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 - option: follow
shorthand: f shorthand: f
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Follow log output. description: Follow log output.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-color - option: no-color
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Produce monochrome output. description: Produce monochrome output.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-log-prefix - option: no-log-prefix
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Don't print prefix in logs. description: Don't print prefix in logs.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: since - option: since
value_type: string value_type: string
description: | description: |
Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: tail - option: tail
value_type: string value_type: string
default_value: all default_value: all
description: | description: |
Number of lines to show from the end of the logs for each container. Number of lines to show from the end of the logs for each container.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: timestamps - option: timestamps
shorthand: t shorthand: t
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Show timestamps. description: Show timestamps.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: until - option: until
value_type: string value_type: string
description: | description: |
Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 - option: all
shorthand: a shorthand: a
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Show all stopped Compose projects description: Show all stopped Compose projects
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: filter - option: filter
value_type: filter value_type: filter
description: Filter output based on conditions provided. description: Filter output based on conditions provided.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: format - option: format
value_type: string value_type: string
default_value: pretty default_value: pretty
description: 'Format the output. Values: [pretty | json].' description: 'Format the output. Values: [pretty | json].'
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: quiet - option: quiet
shorthand: q shorthand: q
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Only display IDs. description: Only display IDs.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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

View File

@ -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 - option: index
value_type: int value_type: int
default_value: "1" default_value: "1"
description: index of the container if service has multiple replicas description: index of the container if service has multiple replicas
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: protocol - option: protocol
value_type: string value_type: string
default_value: tcp default_value: tcp
description: tcp or udp description: tcp or udp
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

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

View File

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

View File

@ -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: The following assumptions are made:
- You are pushing an image you have built locally - You are pushing an image you have built locally
- You have access to the build key - You have access to the build key
Examples Examples
```yaml ```yaml
services: services:
service1: service1:
build: . build: .
image: localhost:5000/yourimage ## goes to local registry image: localhost:5000/yourimage ## goes to local registry
service2: service2:
build: . build: .
image: your-dockerid/yourimage ## goes to your repository on Docker Hub image: your-dockerid/yourimage ## goes to your repository on Docker Hub
``` ```
usage: docker compose push [SERVICE...] 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 - option: ignore-push-failures
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Push what it can and ignores images with push failures description: Push what it can and ignores images with push failures
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 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
after a container is built, but before the container's command is executed) are not updated after a container is built, but before the container's command is executed) are not updated
after restarting. after restarting.
If you are looking to configure a service's restart policy, please refer to 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) [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). or [restart_policy](https://github.com/compose-spec/compose-spec/blob/master/deploy.md#restart_policy).
usage: docker compose restart usage: docker compose restart [OPTIONS] [SERVICE...]
pname: docker compose pname: docker compose
plink: docker_compose.yaml plink: docker_compose.yaml
options: options:
- option: timeout - option: timeout
shorthand: t shorthand: t
value_type: int value_type: int
default_value: "10" default_value: "10"
description: Specify a shutdown timeout in seconds description: Specify a shutdown timeout in seconds
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 By default, anonymous volumes attached to containers are not removed. You can override this with `-v`. To list all
volumes, use `docker volume ls`. 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 ```console
$ docker compose rm $ docker compose rm
Going to remove djangoquickstart_web_run_1 Going to remove djangoquickstart_web_run_1
Are you sure? [yN] y Are you sure? [yN] y
Removing djangoquickstart_web_run_1 ... done Removing djangoquickstart_web_run_1 ... done
``` ```
usage: docker compose rm [SERVICE...] usage: docker compose rm [OPTIONS] [SERVICE...]
pname: docker compose pname: docker compose
plink: docker_compose.yaml plink: docker_compose.yaml
options: options:
- option: all - option: all
shorthand: a shorthand: a
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Deprecated - no effect description: Deprecated - no effect
deprecated: false deprecated: false
hidden: true hidden: true
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: force - option: force
shorthand: f shorthand: f
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Don't ask to confirm removal description: Don't ask to confirm removal
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: stop - option: stop
shorthand: s shorthand: s
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Stop the containers, if required, before removing description: Stop the containers, if required, before removing
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: volumes - option: volumes
shorthand: v shorthand: v
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Remove any anonymous volumes attached to containers description: Remove any anonymous volumes attached to containers
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

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

View File

@ -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`. Stops running containers without removing them. They can be started again with `docker compose start`.
usage: docker compose stop [SERVICE...] usage: docker compose stop [OPTIONS] [SERVICE...]
pname: docker compose pname: docker compose
plink: docker_compose.yaml plink: docker_compose.yaml
options: options:
- option: timeout - option: timeout
shorthand: t shorthand: t
value_type: int value_type: int
default_value: "10" default_value: "10"
description: Specify a shutdown timeout in seconds description: Specify a shutdown timeout in seconds
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

View File

@ -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 ```console
$ docker compose top $ docker compose top
example_foo_1 example_foo_1
UID PID PPID C STIME TTY TIME CMD UID PID PPID C STIME TTY TIME CMD
root 142353 142331 2 15:33 ? 00:00:00 ping localhost -c 5 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

View File

@ -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). 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 When the command exits, all containers are stopped. Running `docker compose up --detach` starts the containers in the
background and leaves them running. background and leaves them running.
If there are existing containers for a service, and the services configuration or image was changed after the If there are existing containers for a service, and the services configuration or image was changed after the
containers creation, `docker compose up` picks up the changes by stopping and recreating the containers containers 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. (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 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`. 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...] 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 - option: abort-on-container-exit
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: | description: |
Stops all containers if any container was stopped. Incompatible with -d Stops all containers if any container was stopped. Incompatible with -d
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: always-recreate-deps - option: always-recreate-deps
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Recreate dependent containers. Incompatible with --no-recreate. description: Recreate dependent containers. Incompatible with --no-recreate.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: attach - option: attach
value_type: stringArray value_type: stringArray
default_value: '[]' default_value: '[]'
description: Attach to service output. description: Attach to service output.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: attach-dependencies - option: attach-dependencies
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Attach to dependent containers. description: Attach to dependent containers.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: build - option: build
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Build images before starting containers. description: Build images before starting containers.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: detach - option: detach
shorthand: d shorthand: d
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: 'Detached mode: Run containers in the background' description: 'Detached mode: Run containers in the background'
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: exit-code-from - option: exit-code-from
value_type: string value_type: string
description: | description: |
Return the exit code of the selected service container. Implies --abort-on-container-exit Return the exit code of the selected service container. Implies --abort-on-container-exit
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: force-recreate - option: force-recreate
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: | description: |
Recreate containers even if their configuration and image haven't changed. Recreate containers even if their configuration and image haven't changed.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-build - option: no-build
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Don't build an image, even if it's missing. description: Don't build an image, even if it's missing.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-color - option: no-color
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Produce monochrome output. description: Produce monochrome output.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-deps - option: no-deps
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Don't start linked services. description: Don't start linked services.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-log-prefix - option: no-log-prefix
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Don't print prefix in logs. description: Don't print prefix in logs.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-recreate - option: no-recreate
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: | description: |
If containers already exist, don't recreate them. Incompatible with --force-recreate. If containers already exist, don't recreate them. Incompatible with --force-recreate.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: no-start - option: no-start
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Don't start the services after creating them. description: Don't start the services after creating them.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: quiet-pull - option: pull
value_type: bool value_type: string
default_value: "false" default_value: missing
description: Pull without printing progress information. description: Pull image before running ("always"|"missing"|"never")
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: remove-orphans - option: quiet-pull
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Remove containers for services not defined in the Compose file. description: Pull without printing progress information.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: renew-anon-volumes - option: remove-orphans
shorthand: V value_type: bool
value_type: bool default_value: "false"
default_value: "false" description: Remove containers for services not defined in the Compose file.
description: | deprecated: false
Recreate anonymous volumes instead of retrieving data from the previous containers. hidden: false
deprecated: false experimental: false
hidden: false experimentalcli: false
experimental: false kubernetes: false
experimentalcli: false swarm: false
kubernetes: false - option: renew-anon-volumes
swarm: false shorthand: V
- option: scale value_type: bool
value_type: stringArray default_value: "false"
default_value: '[]' description: |
description: | Recreate anonymous volumes instead of retrieving data from the previous containers.
Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. deprecated: false
deprecated: false hidden: false
hidden: false experimental: false
experimental: false experimentalcli: false
experimentalcli: false kubernetes: false
kubernetes: false swarm: false
swarm: false - option: scale
- option: timeout value_type: stringArray
shorthand: t default_value: '[]'
value_type: int description: |
default_value: "10" Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present.
description: | deprecated: false
Use this timeout in seconds for container shutdown when attached or when containers are already running. hidden: false
deprecated: false experimental: false
hidden: false experimentalcli: false
experimental: false kubernetes: false
experimentalcli: false swarm: false
kubernetes: false - option: timeout
swarm: false shorthand: t
- option: wait value_type: int
value_type: bool default_value: "10"
default_value: "false" description: |
description: Wait for services to be running|healthy. Implies detached mode. Use this timeout in seconds for container shutdown when attached or when containers are already running.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: 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

View File

@ -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 - option: format
shorthand: f shorthand: f
value_type: string value_type: string
description: 'Format the output. Values: [pretty | json]. (Default: pretty)' description: 'Format the output. Values: [pretty | json]. (Default: pretty)'
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
- option: short - option: short
value_type: bool value_type: bool
default_value: "false" default_value: "false"
description: Shows only Compose's version number. description: Shows only Compose's version number.
deprecated: false deprecated: false
hidden: false hidden: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false
kubernetes: false kubernetes: false
swarm: false swarm: false
deprecated: false deprecated: false
experimental: false experimental: false
experimentalcli: false experimentalcli: false

25
go.mod
View File

@ -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/cnabio/cnab-to-oci v0.3.6
github.com/compose-spec/compose-go v1.2.8 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/containerd/containerd v1.6.7
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e 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.9.0
github.com/sirupsen/logrus v1.8.1
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

44
go.sum
View File

@ -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.6 h1:QVvy4WjQpGyf20xbbeYtRObX+pB8cWNuvvT/e4w1DoQ=
github.com/cnabio/cnab-to-oci v0.3.4/go.mod h1:7f86Z39HUg67wg8dZvxvFpW2pGDjK3RwbJAMJGxTXHQ= 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.4.0 h1:zaYVAZ6lIByr7Jffi20AabfeUwcTrdXfH3X1R5HEm+g=
github.com/compose-spec/compose-go v1.2.8/go.mod h1:813WrDd7NtOl9ZVqswlJ5iCQy3lxI3KYxKkY8EeHQ7w= 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.7 h1:IVikHEHEMZ5SXpUa80tNGNIV7fBigjp+sOcrlzAkPCc=
github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= 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=

View File

@ -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
}

View File

@ -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
) )

View File

@ -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
} }
}() }()
} }

View File

@ -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) { args := flatten(options.Args.Resolve(envResolver(project.Environment)))
s, ok := project.Environment[s]
return s, ok
}))
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 { if service.Build == nil {
imageName := getImageName(service, project.Name) continue
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
} }
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
} }
_, 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 { for i := range project.Services {
imgName := getImageName(s, project.Name) 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) { buildArgs := flatten(service.Build.Args.Resolve(envResolver(project.Environment)))
s, ok := project.Environment[s]
return s, ok
}))
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 secretsProvider, err := addSecretsConfig(project, service)
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)
if err != nil { if err != nil {
return build.Options{}, err return build.Options{}, err
} }
p := secretsprovider.NewSecretProvider(store) sessionConfig = append(sessionConfig, secretsProvider)
sessionConfig = append(sessionConfig, p)
} }
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 { func dockerFilePath(ctxName string, dockerfile string) string {
if urlutil.IsGitURL(context) || filepath.IsAbs(dockerfile) { 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
}

View File

@ -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
} }
} }

View File

@ -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 {

View File

@ -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, linkServiceName+api.Separator+strconv.Itoa(number)),
format(containerName, strings.Join([]string{projectName, linkServiceName, strconv.Itoa(number)}, Separator)), 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, IPv4Address: ipv4Address,
IPv6Address: ipv6Address, IPv6Address: ipv6Address,
LinkLocalIPs: cfg.LinkLocalIPs,
} }
} }
err := s.apiClient().NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{ err := s.apiClient().NetworkConnect(ctx, netwrk, id, &network.EndpointSettings{

View File

@ -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)
} }

View File

@ -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, IPv4Address: ipv4Address,
IPv6Address: ipv6Address, 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 { func isUnixAbs(p string) bool {
return strings.HasPrefix(path, "/") 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

View File

@ -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, api.GetImageNameOrDefault(composetypes.ServiceConfig{Image: "myImage"}, "myProject"), "myImage")
assert.Equal(t, getImageName(types.ServiceConfig{Name: "aService"}, "myProject"), "myProject_aService") 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) {

View File

@ -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 include := oneOffExclude
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true) 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 net.Name == name {
if errdefs.IsNotFound(err) { if err := s.apiClient().NetworkRemove(ctx, net.ID); err != nil {
continue 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)) removed++
return errors.Wrapf(err, fmt.Sprintf("failed to remove network %s", name))
} }
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{}{}
} }

View File

@ -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{

View File

@ -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
}
}

View File

@ -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)
})
}
}

View File

@ -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

View File

@ -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,
} }
} }

View File

@ -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) {

View File

@ -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
} }

View File

@ -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:

View File

@ -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 { func (s *composeService) pause(ctx context.Context, projectName string, options api.PauseOptions) error {
containers, err := s.getContainers(ctx, project, oneOffExclude, false, options.Services...) 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) {

View File

@ -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
} }

View File

@ -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 {

View File

@ -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)

View File

@ -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
}) })

View File

@ -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 {
containers, err := s.getContainers(ctx, projectName, oneOffExclude, true)
observedState, 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...) project := options.Project
if err != nil { if project == nil {
return err 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
} }

View File

@ -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) cmdEnv := types.NewMappingWithEquals(opts.Environment)
projectEnv := env.Resolve(func(s string) (string, bool) { serviceOverrideEnv := cmdEnv.Resolve(func(s string) (string, bool) {
if _, ok := service.Environment[s]; ok { v, ok := envResolver(project.Environment)(s)
return "", false
}
v, ok := 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)

View File

@ -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
} }

View File

@ -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, err := s.getContainers(ctx, projectName, oneOffExclude, true)
containers, project, err := s.actualState(ctx, projectName, options.Services)
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) if !utils.StringContains(options.Services, service) {
return s.stopContainers(ctx, w, containersToStop, options.Timeout) return nil
}
return s.stopContainers(ctx, w, containers.filter(isService(service)).filter(isNotOneOff), options.Timeout)
}) })
} }

View File

@ -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)

View File

@ -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 s.Kill(ctx, project.Name, api.KillOptions{ //nolint:errcheck
Services: project.ServiceNames(), 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

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