Compare commits

...

43 Commits

Author SHA1 Message Date
Joana Hrotko
234036756b upgrade docker versions
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-08-14 13:57:41 +02:00
Joana Hrotko
9c03797f9d initial sync files that modified after image creation
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-08-09 12:11:16 +02:00
Joana Hrotko
485c0eba53 initial sync for root directory
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-08-09 12:11:16 +02:00
Mayank Kapur
69384a9a0f Removes redundant condition from toAPIBuildOptions in build.go
Signed-off-by: Mayank Kapur <kapurm17@gmail.com>
2024-08-05 08:08:41 +02:00
Jan Brasna
1601ead7bc docs: Update docker compose kill usage
Signed-off-by: Jan Brasna <1784648+janbrasna@users.noreply.github.com>
2024-08-05 07:41:53 +02:00
Joana Hrotko
ea4ccf639d Fix stop on file chane for sync-restart action
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-07-25 16:28:47 +02:00
Guillaume Lours
b1850ea4d4 bump engine and cli to v27.1.1, buildx to v0.16.1
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-07-25 16:24:08 +02:00
Guillaume Lours
adba639e88 remove all dependabot update PRs for OTel dependencies
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-07-25 16:23:54 +02:00
Sebastiaan van Stijn
d8518529c4 gp.mod: github.com/gofrs/flock v0.12.1
- fix: missing read-write flag in reopenFDOnError
  fixes a regression that could result in a `ERROR: bad file descriptor`.

b659e1e00a
introduced a regression where `f.flag` would not be in read-write mode
[1]  but read-only [2] which breaks people using NFS protocol.

[1]: b659e1e00a (diff-87c2c4fe0fb43f4b38b4bee45c1b54cfb694c61e311f93b369caa44f6c1323ffR192)
[2]: b659e1e00a (diff-22145325dded38eb5288ed3321a113d8260ccc70747ee04d4551bfd2fba975fdR69)

full diff: https://github.com/gofrs/flock/compare/v0.12.0...v0.12.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-25 10:59:33 +02:00
Sebastiaan van Stijn
c79f15da9e go.mod: golang.org/x/sys v0.22.0
full diff: https://github.com/golang/sys/compare/v0.21.0...v0.22.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-25 10:59:33 +02:00
Sebastiaan van Stijn
3f55382ff0 update to go1.21.12
go1.21.12 (released 2024-07-02) includes security fixes to the net/http package,
as well as bug fixes to the compiler, the go command, the runtime, and the
crypto/x509, net/http, net/netip, and os packages. See the Go 1.21.12 milestone
on our issue tracker for details:

- https://github.com/golang/go/issues?q=milestone%3AGo1.21.12+label%3ACherryPickApproved
- full diff: https://github.com/golang/go/compare/go1.21.11...go1.21.12

From the security mailing:

> Hello gophers,
>
> We have just released Go versions 1.22.5 and 1.21.12, minor point releases.
>
> These minor releases include 1 security fixes following the security policy:
>
> * net/http: denial of service due to improper 100-continue handling
>
>   The net/http HTTP/1.1 client mishandled the case where a server responds
>   to a request with an “Expect: 100-continue” header with a non-informational
>   (200 or higher) status. This mishandling could leave a client connection
>   in an invalid state, where the next request sent on the connection will fail.
>
> An attacker sending a request to a net/http/httputil.ReverseProxy proxy can
> exploit this mishandling to cause a denial of service by sending
> “Expect: 100-continue” requests which elicit a non-informational response
> from the backend. Each such request leaves the proxy with an invalid connection,
> and causes one subsequent request using that connection to fail.
>
> Thanks to Geoff Franks for reporting this issue.
>
> This is CVE-2024-24791 and Go issue https://go.dev/issue/67555.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-25 10:43:39 +02:00
Cody Rigney
44337d2bbf Enhance JSON progress events with more fields.
Signed-off-by: Cody Rigney <cody.rigney@docker.com>
2024-07-23 16:20:27 +02:00
Nicolas De Loof
bc733508d6 bump compose-go v2.1.5
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-07-23 16:01:16 +02:00
Sebastiaan van Stijn
c422b5447c bump github.com/docker/cli v27.1.0
full diffs:

- https://github.com/docker/cli/compare/v27.0.3...v27.1.0
- https://github.com/grpc/grpc-go/compare/v1.59.0...v1.60.1
- https://github.com/open-telemetry/opentelemetry-go/compare/exporters/otlp/otlpmetric/otlpmetricgrpc/v0.42.0...exporters/otlp/otlpmetric/otlpmetricgrpc/v0.44.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-23 15:33:58 +02:00
Sebastiaan van Stijn
e74441c907 bump github.com/docker/docker v27.1.0
full diff: https://github.com/docker/docker/compare/v27.0.3...v27.1.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-23 15:33:58 +02:00
Sebastiaan van Stijn
2bac32a46e bump github.com/containerd/containerd v1.7.20
full diffs:

= containerd: https://github.com/containerd/containerd/compare/v1.7.19...v1.7.20
- google.golang.org/genproto/googleapis/rpc 49dd2c1f3d...995d672761
- google.golang.org/genproto: 49dd2c1f3d...989df2bf70
- google.golang.org/genproto/googleapis/api: 49dd2c1f3d...83a465c022

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-23 15:33:58 +02:00
Sebastiaan van Stijn
f278400fbc gha: add docker 27.1.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-23 15:21:34 +02:00
Suleiman Dibirov
4f9db4d3e6 fix(containers): fix sorting logic by adding secondary sorting for one-off containers
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
2024-07-22 09:32:59 +02:00
guoguangwu
06bf339a42 fix: typos
Signed-off-by: guoguangwu <guoguangwug@gmail.com>
2024-07-17 13:48:13 +01:00
Guillaume Lours
231ea10058 update docs generation to avoid man pages generation
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-07-17 13:01:51 +02:00
Guillaume Lours
46679150d6 bump compose-go to v2.1.4, buildx to v0.16.0, containerd to v1.7.19 and buildx to v0.15.0
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2024-07-17 13:01:51 +02:00
Nicolas De Loof
d3d378b92a restore setEnvWithDotEnv
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-07-11 10:25:04 +02:00
Nicolas De Loof
163cdfd31d empty env variable with no value must be unset in container
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-07-10 14:23:34 +02:00
Nicolas De Loof
25f85938bb exclude unnecessary resources after services have been selected
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2024-07-09 15:12:27 +02:00
Joana Hrotko
cacbca859d change time for stale bot
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-07-09 12:06:54 +02:00
Joana Hrotko
ecac13f272 Remove debug mode and run twice a week
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-07-08 15:26:37 +02:00
Joana Hrotko
14793cc2e4 Add stale workflow
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-07-08 15:26:37 +02:00
Suleiman Dibirov
11d5ecdc75 update docs
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
2024-07-02 08:16:09 +02:00
Suleiman Dibirov
9549a213ba feat(watch): Add --prune option to docker-compose watch command
Signed-off-by: Suleiman Dibirov <idsulik@gmail.com>
2024-07-02 08:16:09 +02:00
Joana Hrotko
da434013e3 Remove COMPOSE_MENU env from e2e tests
Signed-off-by: Joana Hrotko <joana.hrotko@docker.com>
2024-07-01 16:31:12 +01:00
Felix Fontein
ace69c96a7 Use rawjson for the build backend.
Signed-off-by: Felix Fontein <felix@fontein.de>
2024-07-01 15:32:51 +02:00
Felix Fontein
2db04c1e40 Set logging format to JSON.
Signed-off-by: Felix Fontein <felix@fontein.de>
2024-07-01 15:32:51 +02:00
Felix Fontein
8f7cd00481 Format errors as JSON when in JSON progress mode.
Signed-off-by: Felix Fontein <felix@fontein.de>
2024-07-01 15:32:51 +02:00
Felix Fontein
5a6e1a7e2e Pass 'plain' instead of 'json' to build backend
Signed-off-by: Felix Fontein <felix@fontein.de>
2024-07-01 15:32:51 +02:00
Felix Fontein
06545d0668 Add JSON stream progress writer
Signed-off-by: Felix Fontein <felix@fontein.de>
2024-07-01 15:32:51 +02:00
Sebastiaan van Stijn
075fd93452 go.mod: docker/cli, docker/docker v27.0.3
full diffs:

- https://github.com/docker/cli/compare/v27.0.2...v27.0.3
- https://github.com/docker/docker/compare/v27.0.2...v27.0.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-01 14:48:16 +02:00
Sebastiaan van Stijn
d062ad739a gha: test against docker v27.0.3
Switch to the test-channel, using the test.docker.com
script, which has both stable and pre-releases.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-07-01 14:21:38 +02:00
Sebastiaan van Stijn
7cd5209cc2 go.mod: docker/cli, docker/docker v27.0.2
full diffs:

- https://github.com/docker/cli/compare/v27.0.1-rc.1...v27.0.2
- https://github.com/docker/docker/compare/v27.0.1-rc.1...v27.0.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-27 21:16:05 +02:00
Paweł Gronowski
f79c28168b Remove console.Terminal check and use IsTerminal from streams.Out
docker/cli v27 changed the return value of `Err()` to `streams.Out`
which made the typecheck for `console.File` fail.

The check is no longer needed due to the `IsTerminal` method present in
`streams.Out` which also has a special handling for Windows console.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-06-24 14:58:19 +02:00
Albin Kerouanton
6a000dcff1 go.mod: github.com/compose-spec/compose-go v2.1.3
full diff:

- https://github.com/compose-spec/compose-go/compare/v2.1.2...v2.1.3

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-21 14:04:40 +02:00
Albin Kerouanton
2636dcf064 go.mod: docker/docker and docker/cli v27.0.1-rc.1
diffs:

- https://github.com/docker/cli/compare/v26.1.4..v27.0.1-rc.1
- https://github.com/docker/docker/compare/v26.1.4..v27.0.1-rc.1

Co-authored-by: Albin Kerouanton <albinker@gmail.com
Signed-off-by: Albin Kerouanton <albinker@gmail.com
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-21 14:04:40 +02:00
dependabot[bot]
77377f2df6 build(deps): bump github.com/spf13/cobra from 1.8.0 to 1.8.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-21 10:35:57 +02:00
dependabot[bot]
af1bc285a0 build(deps): bump github.com/docker/buildx from 0.15.0 to 0.15.1
Bumps [github.com/docker/buildx](https://github.com/docker/buildx) from 0.15.0 to 0.15.1.
- [Release notes](https://github.com/docker/buildx/releases)
- [Commits](https://github.com/docker/buildx/compare/v0.15.0...v0.15.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-20 18:33:37 +02:00
87 changed files with 1386 additions and 522 deletions

View File

@@ -19,6 +19,5 @@ updates:
- dependency-name: "github.com/containerd/containerd"
# containerd major/minor must be kept in sync with moby
update-types: [ "version-update:semver-major", "version-update:semver-minor" ]
- dependency-name: "go.opentelemetry.io/otel/*"
# OTEL is v1.x but has some parts that are not API stable yet
update-types: [ "version-update:semver-major", "version-update:semver-minor"]
# OTEL dependencies should be upgraded in sync with engine, cli, buildkit and buildx projects
- dependency-name: "go.opentelemetry.io/*"

View File

@@ -144,6 +144,7 @@ jobs:
- 24.0.9
- 25.0.5
- 26.1.4
- 27.1.0
steps:
- name: Prepare
run: |
@@ -158,7 +159,7 @@ jobs:
sudo systemctl stop docker.service
sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-compose-plugin docker-ce-rootless-extras docker-buildx-plugin
sudo apt-get install curl
curl -fsSL https://get.docker.com -o get-docker.sh
curl -fsSL https://test.docker.com -o get-docker.sh
sudo sh ./get-docker.sh --version ${{ matrix.engine }}
- name: Check Docker Version
run: docker --version

23
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: 'Close stale issues'
on:
schedule:
- cron: '0 0 * * 0,3' # at midnight UTC every Sunday and Wednesday
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
days-before-issue-stale: 150 # marks stale after 5 months
days-before-issue-close: 30 # closes 1 month after being marked with no action
stale-issue-label: "stale"
exempt-issue-labels: "kind/feature,kind/enhancement"

View File

@@ -15,7 +15,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
ARG GO_VERSION=1.21.11
ARG GO_VERSION=1.21.12
ARG XX_VERSION=1.2.1
ARG GOLANGCI_LINT_VERSION=v1.55.2
ARG ADDLICENSE_VERSION=v1.0.0
@@ -101,7 +101,6 @@ RUN --mount=type=bind,target=. \
FROM build-base AS test
ARG CGO_ENABLED=0
ARG BUILD_TAGS
ENV COMPOSE_MENU=FALSE
RUN --mount=type=bind,target=. \
--mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/go/pkg/mod \

View File

@@ -13,7 +13,6 @@
# limitations under the License.
PKG := github.com/docker/compose/v2
export COMPOSE_MENU = FALSE
VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always --tags)
GO_LDFLAGS ?= -w -X ${PKG}/internal.Version=${VERSION}

View File

@@ -48,7 +48,6 @@ type buildOptions struct {
func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions, error) {
var SSHKeys []types.SSHKey
var err error
if opts.ssh != "" {
id, path, found := strings.Cut(opts.ssh, "=")
if !found && id != "default" {
@@ -58,19 +57,20 @@ func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions,
ID: id,
Path: path,
})
if err != nil {
return api.BuildOptions{}, err
}
}
builderName := opts.builder
if builderName == "" {
builderName = os.Getenv("BUILDX_BUILDER")
}
uiMode := ui.Mode
if uiMode == ui.ModeJSON {
uiMode = "rawjson"
}
return api.BuildOptions{
Pull: opts.pull,
Push: opts.push,
Progress: ui.Mode,
Progress: uiMode,
Args: types.NewMappingWithEquals(opts.args),
NoCache: opts.noCache,
Quiet: opts.quiet,

View File

@@ -18,6 +18,7 @@ package compose
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
@@ -28,8 +29,10 @@ import (
"syscall"
"github.com/compose-spec/compose-go/v2/cli"
"github.com/compose-spec/compose-go/v2/dotenv"
"github.com/compose-spec/compose-go/v2/loader"
"github.com/compose-spec/compose-go/v2/types"
composegoutils "github.com/compose-spec/compose-go/v2/utils"
"github.com/docker/buildx/util/logutil"
dockercli "github.com/docker/cli/cli"
"github.com/docker/cli/cli-plugins/manager"
@@ -109,6 +112,9 @@ func AdaptCmd(fn CobraCommand) func(cmd *cobra.Command, args []string) error {
Status: err.Error(),
}
}
if ui.Mode == ui.ModeJSON {
err = makeJSONError(err)
}
return err
}
}
@@ -165,6 +171,38 @@ func (o *ProjectOptions) WithServices(dockerCli command.Cli, fn ProjectServicesF
})
}
type jsonErrorData struct {
Error bool `json:"error,omitempty"`
Message string `json:"message,omitempty"`
}
func errorAsJSON(message string) string {
errorMessage := &jsonErrorData{
Error: true,
Message: message,
}
marshal, err := json.Marshal(errorMessage)
if err == nil {
return string(marshal)
} else {
return message
}
}
func makeJSONError(err error) error {
if err == nil {
return nil
}
var statusErr dockercli.StatusError
if errors.As(err, &statusErr) {
return dockercli.StatusError{
StatusCode: statusErr.StatusCode,
Status: errorAsJSON(statusErr.Status),
}
}
return fmt.Errorf("%s", errorAsJSON(err.Error()))
}
func (o *ProjectOptions) addProjectFlags(f *pflag.FlagSet) {
f.StringArrayVar(&o.Profiles, "profile", []string{}, "Specify a profile to enable")
f.StringVarP(&o.ProjectName, "project-name", "p", "", "Project name")
@@ -306,11 +344,14 @@ func (o *ProjectOptions) ToProject(ctx context.Context, dockerCli command.Cli, s
project.Services[name] = s
}
project, err = project.WithSelectedServices(services)
if err != nil {
return nil, tracing.Metrics{}, err
}
if !o.All {
project = project.WithoutUnnecessaryResources()
}
project, err = project.WithSelectedServices(services)
return project, metrics, err
}
@@ -411,6 +452,11 @@ func RootCommand(dockerCli command.Cli, backend Backend) *cobra.Command { //noli
if verbose {
logrus.SetLevel(logrus.TraceLevel)
}
err := setEnvWithDotEnv(opts)
if err != nil {
return err
}
if noAnsi {
if ansi != "auto" {
return errors.New(`cannot specify DEPRECATED "--no-ansi" and "--ansi". Please use only "--ansi"`)
@@ -453,6 +499,9 @@ func RootCommand(dockerCli command.Cli, backend Backend) *cobra.Command { //noli
ui.Mode = ui.ModePlain
case ui.ModeQuiet, "none":
ui.Mode = ui.ModeQuiet
case ui.ModeJSON:
ui.Mode = ui.ModeJSON
logrus.SetFormatter(&logrus.JSONFormatter{})
default:
return fmt.Errorf("unsupported --progress value %q", opts.Progress)
}
@@ -499,7 +548,7 @@ func RootCommand(dockerCli command.Cli, backend Backend) *cobra.Command { //noli
}
// dry run detection
ctx, err := backend.DryRunMode(ctx, dryRun)
ctx, err = backend.DryRunMode(ctx, dryRun)
if err != nil {
return err
}
@@ -599,10 +648,35 @@ func RootCommand(dockerCli command.Cli, backend Backend) *cobra.Command { //noli
return c
}
func setEnvWithDotEnv(opts ProjectOptions) error {
options, err := cli.NewProjectOptions(opts.ConfigPaths,
cli.WithWorkingDirectory(opts.ProjectDir),
cli.WithOsEnv,
cli.WithEnvFiles(opts.EnvFiles...),
cli.WithDotEnv,
)
if err != nil {
return nil
}
envFromFile, err := dotenv.GetEnvFromFile(composegoutils.GetAsEqualsMap(os.Environ()), options.EnvFiles)
if err != nil {
return nil
}
for k, v := range envFromFile {
if _, ok := os.LookupEnv(k); !ok {
if err = os.Setenv(k, v); err != nil {
return nil
}
}
}
return err
}
var printerModes = []string{
ui.ModeAuto,
ui.ModeTTY,
ui.ModePlain,
ui.ModeJSON,
ui.ModeQuiet,
}

View File

@@ -32,7 +32,8 @@ import (
type watchOptions struct {
*ProjectOptions
noUp bool
prune bool
noUp bool
}
func watchCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service) *cobra.Command {
@@ -58,6 +59,7 @@ func watchCommand(p *ProjectOptions, dockerCli command.Cli, backend api.Service)
}
cmd.Flags().BoolVar(&buildOpts.quiet, "quiet", false, "hide build output")
cmd.Flags().BoolVar(&watchOpts.prune, "prune", false, "Prune dangling images on rebuild")
cmd.Flags().BoolVar(&watchOpts.noUp, "no-up", false, "Do not build & start services before watching")
return cmd
}
@@ -118,5 +120,6 @@ func runWatch(ctx context.Context, dockerCli command.Cli, backend api.Service, w
return backend.Watch(ctx, project, services, api.WatchOptions{
Build: &build,
LogTo: consumer,
Prune: watchOpts.prune,
})
}

View File

@@ -98,7 +98,7 @@ func (l *logConsumer) Log(container, message string) {
l.write(l.stdout, container, message)
}
// Log formats a log message as received from name/container
// Err formats a log message as received from name/container
func (l *logConsumer) Err(container, message string) {
l.write(l.stderr, container, message)
}

View File

@@ -1,7 +1,150 @@
# docker compose
<!---MARKER_GEN_START-->
Define and run multi-container applications with Docker
You can use the compose subcommand, `docker compose [-f <arg>...] [options] [COMMAND] [ARGS...]`, to build and manage
multiple services in Docker containers.
### Use `-f` to specify the name and path of one or more Compose files
Use the `-f` flag to specify the location of a Compose configuration file.
#### Specifying multiple Compose files
You can supply multiple `-f` configuration files. When you supply multiple files, Compose combines them into a single
configuration. Compose builds the configuration in the order you supply the files. Subsequent files override and add
to their predecessors.
For example, consider this command line:
```console
$ docker compose -f docker-compose.yml -f docker-compose.admin.yml run backup_db
```
The `docker-compose.yml` file might specify a `webapp` service.
```yaml
services:
webapp:
image: examples/web
ports:
- "8000:8000"
volumes:
- "/data"
```
If the `docker-compose.admin.yml` also specifies this same service, any matching fields override the previous file.
New values, add to the `webapp` service configuration.
```yaml
services:
webapp:
build: .
environment:
- DEBUG=1
```
When you use multiple Compose files, all paths in the files are relative to the first configuration file specified
with `-f`. You can use the `--project-directory` option to override this base path.
Use a `-f` with `-` (dash) as the filename to read the configuration from stdin. When stdin is used all paths in the
configuration are relative to the current working directory.
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.
#### Specifying a path to a single Compose file
You can use the `-f` flag to specify a path to a Compose file that is not located in the current directory, either
from the command line or by setting up a `COMPOSE_FILE` environment variable in your shell or in an environment file.
For an example of using the `-f` option at the command line, suppose you are running the Compose Rails sample, and
have a `compose.yaml` file in a directory called `sandbox/rails`. You can use a command like `docker compose pull` to
get the postgres image for the db service from anywhere by using the `-f` flag as follows:
```console
$ docker compose -f ~/sandbox/rails/compose.yaml pull db
```
### Use `-p` to specify a project name
Each configuration has a project name. Compose sets the project name using
the following mechanisms, in order of precedence:
- The `-p` command line flag
- The `COMPOSE_PROJECT_NAME` environment variable
- The top level `name:` variable from the config file (or the last `name:`
from a series of config files specified using `-f`)
- The `basename` of the project directory containing the config file (or
containing the first config file specified using `-f`)
- The `basename` of the current directory if no config file is specified
Project names must contain only lowercase letters, decimal digits, dashes,
and underscores, and must begin with a lowercase letter or decimal digit. If
the `basename` of the project directory or current directory violates this
constraint, you must use one of the other mechanisms.
```console
$ docker compose -p my_project ps -a
NAME SERVICE STATUS PORTS
my_project_demo_1 demo running
$ docker compose -p my_project logs
demo_1 | PING localhost (127.0.0.1): 56 data bytes
demo_1 | 64 bytes from 127.0.0.1: seq=0 ttl=64 time=0.095 ms
```
### Use profiles to enable optional services
Use `--profile` to specify one or more active profiles
Calling `docker compose --profile frontend up` starts the services with the profile `frontend` and services
without any specified profiles.
You can also enable multiple profiles, e.g. with `docker compose --profile frontend --profile debug up` the profiles `frontend` and `debug` is enabled.
Profiles can also be set by `COMPOSE_PROFILES` environment variable.
### Configuring parallelism
Use `--parallel` to specify the maximum level of parallelism for concurrent engine calls.
Calling `docker compose --parallel 1 pull` pulls the pullable images defined in the Compose file
one at a time. This can also be used to control build concurrency.
Parallelism can also be set by the `COMPOSE_PARALLEL_LIMIT` environment variable.
### Set up environment variables
You can set environment variables for various docker compose options, including the `-f`, `-p` and `--profiles` flags.
Setting the `COMPOSE_FILE` environment variable is equivalent to passing the `-f` flag,
`COMPOSE_PROJECT_NAME` environment variable does the same as the `-p` flag,
`COMPOSE_PROFILES` environment variable is equivalent to the `--profiles` flag
and `COMPOSE_PARALLEL_LIMIT` does the same as the `--parallel` flag.
If flags are explicitly set on the command line, the associated environment variable is ignored.
Setting the `COMPOSE_IGNORE_ORPHANS` environment variable to `true` stops docker compose from detecting orphaned
containers for the project.
Setting the `COMPOSE_MENU` environment variable to `false` disables the helper menu when running `docker compose up`
in attached mode. Alternatively, you can also run `docker compose up --menu=false` to disable the helper menu.
### Use Dry Run mode to test your command
Use `--dry-run` flag to test a command without changing your application stack state.
Dry Run mode shows you all the steps Compose applies when executing a command, for example:
```console
$ docker compose --dry-run up --build -d
[+] Pulling 1/1
✔ DRY-RUN MODE - db Pulled 0.9s
[+] Running 10/8
✔ DRY-RUN MODE - build service backend 0.0s
✔ DRY-RUN MODE - ==> ==> writing image dryRun-754a08ddf8bcb1cf22f310f09206dd783d42f7dd 0.0s
✔ DRY-RUN MODE - ==> ==> naming to nginx-golang-mysql-backend 0.0s
✔ DRY-RUN MODE - Network nginx-golang-mysql_default Created 0.0s
✔ DRY-RUN MODE - Container nginx-golang-mysql-db-1 Created 0.0s
✔ DRY-RUN MODE - Container nginx-golang-mysql-backend-1 Created 0.0s
✔ DRY-RUN MODE - Container nginx-golang-mysql-proxy-1 Created 0.0s
✔ DRY-RUN MODE - Container nginx-golang-mysql-db-1 Healthy 0.5s
✔ DRY-RUN MODE - Container nginx-golang-mysql-backend-1 Started 0.0s
✔ DRY-RUN MODE - Container nginx-golang-mysql-proxy-1 Started Started
```
From the example above, you can see that the first step is to pull the image defined by `db` service, then build the `backend` service.
Next, the containers are created. The `db` service is started, and the `backend` and `proxy` wait until the `db` service is healthy before starting.
Dry Run mode works with almost all commands. You cannot use Dry Run mode with a command that doesn't change the state of a Compose stack such as `ps`, `ls`, `logs` for example.
### Subcommands
@@ -43,15 +186,15 @@ Define and run multi-container applications with Docker
| Name | Type | Default | Description |
|:-----------------------|:--------------|:--------|:----------------------------------------------------------------------------------------------------|
| `--all-resources` | | | Include all resources, even those not used by services |
| `--all-resources` | `bool` | | Include all resources, even those not used by services |
| `--ansi` | `string` | `auto` | Control when to print ANSI control characters ("never"\|"always"\|"auto") |
| `--compatibility` | | | Run compose in backward compatibility mode |
| `--dry-run` | | | Execute command in dry run mode |
| `--compatibility` | `bool` | | Run compose in backward compatibility mode |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--env-file` | `stringArray` | | Specify an alternate environment file |
| `-f`, `--file` | `stringArray` | | Compose configuration files |
| `--parallel` | `int` | `-1` | Control max parallelism, -1 for unlimited |
| `--profile` | `stringArray` | | Specify a profile to enable |
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, quiet) |
| `--progress` | `string` | `auto` | Set type of progress output (auto, tty, plain, json, quiet) |
| `--project-directory` | `string` | | Specify an alternate working directory<br>(default: the path of the, first specified, Compose file) |
| `-p`, `--project-name` | `string` | | Project name |

View File

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

View File

@@ -5,14 +5,14 @@ EXPERIMENTAL - Generate a graphviz graph from your compose file
### Options
| Name | Type | Default | Description |
|:---------------------|:------|:--------|:---------------------------------------------------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--image` | | | Include service's image name in output graph |
| `--indentation-size` | `int` | `1` | Number of tabs or spaces to use for indentation |
| `--networks` | | | Include service's attached networks in output graph |
| `--ports` | | | Include service's exposed ports in output graph |
| `--spaces` | | | If given, space character ' ' will be used to indent,<br>otherwise tab character '\t' will be used |
| Name | Type | Default | Description |
|:---------------------|:-------|:--------|:---------------------------------------------------------------------------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--image` | `bool` | | Include service's image name in output graph |
| `--indentation-size` | `int` | `1` | Number of tabs or spaces to use for indentation |
| `--networks` | `bool` | | Include service's attached networks in output graph |
| `--ports` | `bool` | | Include service's exposed ports in output graph |
| `--spaces` | `bool` | | If given, space character ' ' will be used to indent,<br>otherwise tab character '\t' will be used |
<!---MARKER_GEN_END-->

View File

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

View File

@@ -1,7 +1,15 @@
# docker compose build
<!---MARKER_GEN_START-->
Build or rebuild services
Services are built once and then tagged, by default as `project-service`.
If the Compose file specifies an
[image](https://github.com/compose-spec/compose-spec/blob/master/spec.md#image) name,
the image is tagged with that name, substituting any variables beforehand. See
[variable interpolation](https://github.com/compose-spec/compose-spec/blob/master/spec.md#interpolation).
If you change a service's `Dockerfile` or the contents of its build directory,
run `docker compose build` to rebuild it.
### Options
@@ -9,14 +17,14 @@ Build or rebuild services
|:----------------------|:--------------|:--------|:------------------------------------------------------------------------------------------------------------|
| `--build-arg` | `stringArray` | | Set build-time variables for services |
| `--builder` | `string` | | Set builder to use |
| `--dry-run` | | | Execute command in dry run mode |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `-m`, `--memory` | `bytes` | `0` | Set memory limit for the build container. Not supported by BuildKit. |
| `--no-cache` | | | Do not use cache when building the image |
| `--pull` | | | Always attempt to pull a newer version of the image |
| `--push` | | | Push service images |
| `-q`, `--quiet` | | | Don't print anything to STDOUT |
| `--no-cache` | `bool` | | Do not use cache when building the image |
| `--pull` | `bool` | | Always attempt to pull a newer version of the image |
| `--push` | `bool` | | Push service images |
| `-q`, `--quiet` | `bool` | | Don't print anything to STDOUT |
| `--ssh` | `string` | | Set SSH authentications used when building service images. (use 'default' for using your default SSH Agent) |
| `--with-dependencies` | | | Also build dependencies (transitively) |
| `--with-dependencies` | `bool` | | Also build dependencies (transitively) |
<!---MARKER_GEN_END-->

View File

@@ -1,7 +1,9 @@
# docker compose convert
<!---MARKER_GEN_START-->
Parse, resolve and render compose file in canonical format
`docker compose config` renders the actual data model to be applied on the Docker Engine.
It merges the Compose files set by `-f` flags, resolves variables in the Compose file, and expands short-notation into
the canonical format.
### Aliases
@@ -11,22 +13,22 @@ Parse, resolve and render compose file in canonical format
| Name | Type | Default | Description |
|:--------------------------|:---------|:--------|:----------------------------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--environment` | | | Print environment used for interpolation. |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--environment` | `bool` | | Print environment used for interpolation. |
| `--format` | `string` | `yaml` | Format the output. Values: [yaml \| json] |
| `--hash` | `string` | | Print the service config hash, one per line. |
| `--images` | | | Print the image names, one per line. |
| `--no-consistency` | | | Don't check model consistency - warning: may produce invalid Compose output |
| `--no-interpolate` | | | Don't interpolate environment variables |
| `--no-normalize` | | | Don't normalize compose model |
| `--no-path-resolution` | | | Don't resolve file paths |
| `--images` | `bool` | | Print the image names, one per line. |
| `--no-consistency` | `bool` | | Don't check model consistency - warning: may produce invalid Compose output |
| `--no-interpolate` | `bool` | | Don't interpolate environment variables |
| `--no-normalize` | `bool` | | Don't normalize compose model |
| `--no-path-resolution` | `bool` | | Don't resolve file paths |
| `-o`, `--output` | `string` | | Save to file (default to stdout) |
| `--profiles` | | | Print the profile names, one per line. |
| `-q`, `--quiet` | | | Only validate the configuration, don't print anything |
| `--resolve-image-digests` | | | Pin image tags to digests |
| `--services` | | | Print the service names, one per line. |
| `--variables` | | | Print model variables and default values. |
| `--volumes` | | | Print the volume names, one per line. |
| `--profiles` | `bool` | | Print the profile names, one per line. |
| `-q`, `--quiet` | `bool` | | Only validate the configuration, don't print anything |
| `--resolve-image-digests` | `bool` | | Pin image tags to digests |
| `--services` | `bool` | | Print the service names, one per line. |
| `--variables` | `bool` | | Print model variables and default values. |
| `--volumes` | `bool` | | Print the volume names, one per line. |
<!---MARKER_GEN_END-->

View File

@@ -5,12 +5,12 @@ Copy files/folders between a service container and the local filesystem
### Options
| Name | Type | Default | Description |
|:----------------------|:------|:--------|:--------------------------------------------------------|
| `-a`, `--archive` | | | Archive mode (copy all uid/gid information) |
| `--dry-run` | | | Execute command in dry run mode |
| `-L`, `--follow-link` | | | Always follow symbol link in SRC_PATH |
| `--index` | `int` | `0` | Index of the container if service has multiple replicas |
| Name | Type | Default | Description |
|:----------------------|:-------|:--------|:--------------------------------------------------------|
| `-a`, `--archive` | `bool` | | Archive mode (copy all uid/gid information) |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `-L`, `--follow-link` | `bool` | | Always follow symbol link in SRC_PATH |
| `--index` | `int` | `0` | Index of the container if service has multiple replicas |
<!---MARKER_GEN_END-->

View File

@@ -7,14 +7,14 @@ Creates containers for a service
| Name | Type | Default | Description |
|:-------------------|:--------------|:---------|:----------------------------------------------------------------------------------------------|
| `--build` | | | Build images before starting containers |
| `--dry-run` | | | Execute command in dry run mode |
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed |
| `--no-build` | | | Don't build an image, even if it's policy |
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
| `--build` | `bool` | | Build images before starting containers |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--force-recreate` | `bool` | | Recreate containers even if their configuration and image haven't changed |
| `--no-build` | `bool` | | Don't build an image, even if it's policy |
| `--no-recreate` | `bool` | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
| `--pull` | `string` | `policy` | Pull image before running ("always"\|"missing"\|"never"\|"build") |
| `--quiet-pull` | | | Pull without printing progress information |
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file |
| `--quiet-pull` | `bool` | | Pull without printing progress information |
| `--remove-orphans` | `bool` | | Remove containers for services not defined in the Compose file |
| `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. |

View File

@@ -1,17 +1,29 @@
# docker compose down
<!---MARKER_GEN_START-->
Stop and remove containers, networks
Stops containers and removes containers, networks, volumes, and images created by `up`.
By default, the only things removed are:
- Containers for services defined in the Compose file.
- Networks defined in the networks section of the Compose file.
- The default network, if one is used.
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 are not automatically
mounted by a subsequent `up`. For data that needs to persist between updates, use explicit paths as bind mounts or
named volumes.
### Options
| Name | Type | Default | Description |
|:-------------------|:---------|:--------|:------------------------------------------------------------------------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--remove-orphans` | `bool` | | Remove containers for services not defined in the Compose file |
| `--rmi` | `string` | | Remove images used by services. "local" remove only images that don't have a custom tag ("local"\|"all") |
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |
| `-v`, `--volumes` | | | Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers |
| `-v`, `--volumes` | `bool` | | Remove named volumes declared in the "volumes" section of the Compose file and anonymous volumes attached to containers |
<!---MARKER_GEN_END-->

View File

@@ -1,14 +1,32 @@
# docker compose events
<!---MARKER_GEN_START-->
Receive real time events from containers
Stream container events for every container in the project.
With the `--json` flag, a json object is printed one per line with the format:
```json
{
"time": "2015-11-20T18:01:03.615550",
"type": "container",
"action": "create",
"id": "213cf7...5fc39a",
"service": "web",
"attributes": {
"name": "application_web_1",
"image": "alpine:edge"
}
}
```
The events that can be received using this can be seen [here](/reference/cli/docker/system/events/#object-types).
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--json` | | | Output events as a stream of json objects |
| Name | Type | Default | Description |
|:------------|:-------|:--------|:------------------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--json` | `bool` | | Output events as a stream of json objects |
<!---MARKER_GEN_END-->

View File

@@ -1,18 +1,21 @@
# docker compose exec
<!---MARKER_GEN_START-->
Execute a command in a running container
This is the equivalent of `docker exec` targeting a Compose service.
With this subcommand, you can run arbitrary commands in your services. Commands allocate a TTY by default, so
you can use a command such as `docker compose exec web sh` to get an interactive prompt.
### Options
| Name | Type | Default | Description |
|:------------------|:--------------|:--------|:---------------------------------------------------------------------------------|
| `-d`, `--detach` | | | Detached mode: Run command in the background |
| `--dry-run` | | | Execute command in dry run mode |
| `-d`, `--detach` | `bool` | | Detached mode: Run command in the background |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `-e`, `--env` | `stringArray` | | Set environment variables |
| `--index` | `int` | `0` | Index of the container if service has multiple replicas |
| `-T`, `--no-TTY` | `bool` | `true` | Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY. |
| `--privileged` | | | Give extended privileges to the process |
| `--privileged` | `bool` | | Give extended privileges to the process |
| `-u`, `--user` | `string` | | Run the command as this user |
| `-w`, `--workdir` | `string` | | Path to workdir directory for this command |

View File

@@ -7,9 +7,9 @@ List images used by the created containers
| Name | Type | Default | Description |
|:----------------|:---------|:--------|:-------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--format` | `string` | `table` | Format the output. Values: [table \| json] |
| `-q`, `--quiet` | | | Only display IDs |
| `-q`, `--quiet` | `bool` | | Only display IDs |
<!---MARKER_GEN_END-->

View File

@@ -1,14 +1,18 @@
# docker compose kill
<!---MARKER_GEN_START-->
Force stop service containers
Forces running containers to stop by sending a `SIGKILL` signal. Optionally the signal can be passed, for example:
```console
$ docker compose kill -s SIGINT
```
### Options
| Name | Type | Default | Description |
|:-------------------|:---------|:----------|:---------------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--remove-orphans` | `bool` | | Remove containers for services not defined in the Compose file |
| `-s`, `--signal` | `string` | `SIGKILL` | SIGNAL to send to the container |
@@ -19,5 +23,5 @@ Force stop service containers
Forces running containers to stop by sending a `SIGKILL` signal. Optionally the signal can be passed, for example:
```console
$ docker-compose kill -s SIGINT
$ docker compose kill -s SIGINT
```

View File

@@ -1,20 +1,20 @@
# docker compose logs
<!---MARKER_GEN_START-->
View output from containers
Displays log output from services
### Options
| Name | Type | Default | Description |
|:---------------------|:---------|:--------|:-----------------------------------------------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `-f`, `--follow` | | | Follow log output |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `-f`, `--follow` | `bool` | | Follow log output |
| `--index` | `int` | `0` | index of the container if service has multiple replicas |
| `--no-color` | | | Produce monochrome output |
| `--no-log-prefix` | | | Don't print prefix in logs |
| `--no-color` | `bool` | | Produce monochrome output |
| `--no-log-prefix` | `bool` | | Don't print prefix in logs |
| `--since` | `string` | | Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) |
| `-n`, `--tail` | `string` | `all` | Number of lines to show from the end of the logs for each container |
| `-t`, `--timestamps` | | | Show timestamps |
| `-t`, `--timestamps` | `bool` | | Show timestamps |
| `--until` | `string` | | Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes) |

View File

@@ -1,17 +1,17 @@
# docker compose ls
<!---MARKER_GEN_START-->
List running compose projects
Lists running Compose projects
### Options
| Name | Type | Default | Description |
|:----------------|:---------|:--------|:-------------------------------------------|
| `-a`, `--all` | | | Show all stopped Compose projects |
| `--dry-run` | | | Execute command in dry run mode |
| `-a`, `--all` | `bool` | | Show all stopped Compose projects |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--filter` | `filter` | | Filter output based on conditions provided |
| `--format` | `string` | `table` | Format the output. Values: [table \| json] |
| `-q`, `--quiet` | | | Only display IDs |
| `-q`, `--quiet` | `bool` | | Only display IDs |
<!---MARKER_GEN_END-->

View File

@@ -1,13 +1,13 @@
# docker compose pause
<!---MARKER_GEN_START-->
Pause services
Pauses running containers of a service. They can be unpaused with `docker compose unpause`.
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| Name | Type | Default | Description |
|:------------|:-------|:--------|:--------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
<!---MARKER_GEN_END-->

View File

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

View File

@@ -1,20 +1,35 @@
# docker compose ps
<!---MARKER_GEN_START-->
List containers
Lists containers for a Compose project, with current status and exposed ports.
```console
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
example-foo-1 alpine "/entrypoint.…" foo 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp
```
By default, only running containers are shown. `--all` flag can be used to include stopped containers.
```console
$ docker compose ps --all
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
example-foo-1 alpine "/entrypoint.…" foo 4 seconds ago Up 2 seconds 0.0.0.0:8080->80/tcp
example-bar-1 alpine "/entrypoint.…" bar 4 seconds ago exited (0)
```
### Options
| Name | Type | Default | Description |
|:----------------------|:--------------|:--------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `-a`, `--all` | | | Show all stopped containers (including those created by the run command) |
| `--dry-run` | | | Execute command in dry run mode |
| `-a`, `--all` | `bool` | | Show all stopped containers (including those created by the run command) |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| [`--filter`](#filter) | `string` | | Filter services by a property (supported filters: status) |
| [`--format`](#format) | `string` | `table` | Format output using a custom template:<br>'table': Print output in table format with column headers (default)<br>'table TEMPLATE': Print output in table format using the given Go template<br>'json': Print in JSON format<br>'TEMPLATE': Print output using the given Go template.<br>Refer to https://docs.docker.com/go/formatting/ for more information about formatting output with templates |
| `--no-trunc` | | | Don't truncate output |
| `--no-trunc` | `bool` | | Don't truncate output |
| `--orphans` | `bool` | `true` | Include orphaned services (not declared by project) |
| `-q`, `--quiet` | | | Only display IDs |
| `--services` | | | Display services |
| `-q`, `--quiet` | `bool` | | Only display IDs |
| `--services` | `bool` | | Display services |
| [`--status`](#status) | `stringArray` | | Filter services by status. Values: [paused \| restarting \| removing \| running \| dead \| created \| exited] |

View File

@@ -1,18 +1,18 @@
# docker compose pull
<!---MARKER_GEN_START-->
Pull service images
Pulls an image associated with a service defined in a `compose.yaml` file, but does not start containers based on those images
### Options
| Name | Type | Default | Description |
|:-------------------------|:---------|:--------|:-------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--ignore-buildable` | | | Ignore images that can be built |
| `--ignore-pull-failures` | | | Pull what it can and ignores images with pull failures |
| `--include-deps` | | | Also pull services declared as dependencies |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--ignore-buildable` | `bool` | | Ignore images that can be built |
| `--ignore-pull-failures` | `bool` | | Pull what it can and ignores images with pull failures |
| `--include-deps` | `bool` | | Also pull services declared as dependencies |
| `--policy` | `string` | | Apply pull policy ("missing"\|"always") |
| `-q`, `--quiet` | | | Pull without printing progress information |
| `-q`, `--quiet` | `bool` | | Pull without printing progress information |
<!---MARKER_GEN_END-->

View File

@@ -1,16 +1,33 @@
# docker compose push
<!---MARKER_GEN_START-->
Push service images
Pushes images for services to their respective registry/repository.
The following assumptions are made:
- You are pushing an image you have built locally
- You have access to the build key
Examples
```yaml
services:
service1:
build: .
image: localhost:5000/yourimage ## goes to local registry
service2:
build: .
image: your-dockerid/yourimage ## goes to your repository on Docker Hub
```
### Options
| Name | Type | Default | Description |
|:-------------------------|:-----|:--------|:-------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--ignore-push-failures` | | | Push what it can and ignores images with push failures |
| `--include-deps` | | | Also push images of services declared as dependencies |
| `-q`, `--quiet` | | | Push without printing progress information |
| Name | Type | Default | Description |
|:-------------------------|:-------|:--------|:-------------------------------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--ignore-push-failures` | `bool` | | Push what it can and ignores images with push failures |
| `--include-deps` | `bool` | | Also push images of services declared as dependencies |
| `-q`, `--quiet` | `bool` | | Push without printing progress information |
<!---MARKER_GEN_END-->

View File

@@ -1,15 +1,24 @@
# docker compose restart
<!---MARKER_GEN_START-->
Restart service containers
Restarts all stopped and running services, or the specified services only.
If you make changes to your `compose.yml` configuration, these changes are not reflected
after running this command. For example, changes to environment variables (which are added
after a container is built, but before the container's command is executed) are not updated
after restarting.
If you are looking to configure a service's restart policy, refer to
[restart](https://github.com/compose-spec/compose-spec/blob/master/spec.md#restart)
or [restart_policy](https://github.com/compose-spec/compose-spec/blob/master/deploy.md#restart_policy).
### Options
| Name | Type | Default | Description |
|:------------------|:------|:--------|:--------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--no-deps` | | | Don't restart dependent services |
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |
| Name | Type | Default | Description |
|:------------------|:-------|:--------|:--------------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--no-deps` | `bool` | | Don't restart dependent services |
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |
<!---MARKER_GEN_END-->

View File

@@ -1,21 +1,30 @@
# docker compose rm
<!---MARKER_GEN_START-->
Removes stopped service containers
Removes stopped service containers.
By default, anonymous volumes attached to containers will not be removed. You
can override this with -v. To list all volumes, use "docker volume ls".
By default, anonymous volumes attached to containers are not removed. You can override this with `-v`. To list all
volumes, use `docker volume ls`.
Any data which is not in a volume will be 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`:
```console
$ docker compose rm
Going to remove djangoquickstart_web_run_1
Are you sure? [yN] y
Removing djangoquickstart_web_run_1 ... done
```
### Options
| Name | Type | Default | Description |
|:------------------|:-----|:--------|:----------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `-f`, `--force` | | | Don't ask to confirm removal |
| `-s`, `--stop` | | | Stop the containers, if required, before removing |
| `-v`, `--volumes` | | | Remove any anonymous volumes attached to containers |
| Name | Type | Default | Description |
|:------------------|:-------|:--------|:----------------------------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `-f`, `--force` | `bool` | | Don't ask to confirm removal |
| `-s`, `--stop` | `bool` | | Stop the containers, if required, before removing |
| `-v`, `--volumes` | `bool` | | Remove any anonymous volumes attached to containers |
<!---MARKER_GEN_END-->

View File

@@ -1,30 +1,82 @@
# docker compose run
<!---MARKER_GEN_START-->
Run a one-off command on a service
Runs a one-time command against a service.
The following command starts the `web` service and runs `bash` as its command:
```console
$ docker compose run web bash
```
Commands you use with run start in new containers with configuration defined by that of the service,
including volumes, links, and other details. However, there are two important differences:
First, the command passed by `run` overrides the command defined in the service configuration. For example, if the
`web` service configuration is started with `bash`, then `docker compose run web python app.py` overrides it with
`python app.py`.
The second difference is that the `docker compose run` command does not create any of the ports specified in the
service configuration. This prevents port collisions with already-open ports. If you do want the services ports
to be created and mapped to the host, specify the `--service-ports`
```console
$ docker compose run --service-ports web python manage.py shell
```
Alternatively, manual port mapping can be specified with the `--publish` or `-p` options, just as when using docker run:
```console
$ docker compose run --publish 8080:80 -p 2022:22 -p 127.0.0.1:2021:21 web python manage.py shell
```
If you start a service configured with links, the run command first checks to see if the linked service is running
and starts the service if it is stopped. Once all the linked services are running, the run executes the command you
passed it. For example, you could run:
```console
$ docker compose run db psql -h db -U docker
```
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:
```console
$ 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:
```console
$ docker compose run --rm web python manage.py db upgrade
```
This runs a database upgrade script, and removes the container when finished running, even if a restart policy is
specified in the service configuration.
### Options
| Name | Type | Default | Description |
|:------------------------|:--------------|:--------|:---------------------------------------------------------------------------------|
| `--build` | | | Build image before starting container |
| `--build` | `bool` | | Build image before starting container |
| `--cap-add` | `list` | | Add Linux capabilities |
| `--cap-drop` | `list` | | Drop Linux capabilities |
| `-d`, `--detach` | | | Run container in background and print container ID |
| `--dry-run` | | | Execute command in dry run mode |
| `-d`, `--detach` | `bool` | | Run container in background and print container ID |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--entrypoint` | `string` | | Override the entrypoint of the image |
| `-e`, `--env` | `stringArray` | | Set environment variables |
| `-i`, `--interactive` | `bool` | `true` | Keep STDIN open even if not attached |
| `-l`, `--label` | `stringArray` | | Add or override a label |
| `--name` | `string` | | Assign a name to the container |
| `-T`, `--no-TTY` | `bool` | `true` | Disable pseudo-TTY allocation (default: auto-detected) |
| `--no-deps` | | | Don't start linked services |
| `--no-deps` | `bool` | | Don't start linked services |
| `-p`, `--publish` | `stringArray` | | Publish a container's port(s) to the host |
| `--quiet-pull` | | | Pull without printing progress information |
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file |
| `--rm` | | | Automatically remove the container when it exits |
| `-P`, `--service-ports` | | | Run command with all service's ports enabled and mapped to the host |
| `--use-aliases` | | | Use the service's network useAliases in the network(s) the container connects to |
| `--quiet-pull` | `bool` | | Pull without printing progress information |
| `--remove-orphans` | `bool` | | Remove containers for services not defined in the Compose file |
| `--rm` | `bool` | | Automatically remove the container when it exits |
| `-P`, `--service-ports` | `bool` | | Run command with all service's ports enabled and mapped to the host |
| `--use-aliases` | `bool` | | Use the service's network useAliases in the network(s) the container connects to |
| `-u`, `--user` | `string` | | Run as specified username or uid |
| `-v`, `--volume` | `stringArray` | | Bind mount a volume |
| `-w`, `--workdir` | `string` | | Working directory inside the container |

View File

@@ -5,10 +5,10 @@ Scale services
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--no-deps` | | | Don't start linked services |
| Name | Type | Default | Description |
|:------------|:-------|:--------|:--------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--no-deps` | `bool` | | Don't start linked services |
<!---MARKER_GEN_END-->

View File

@@ -1,13 +1,13 @@
# docker compose start
<!---MARKER_GEN_START-->
Start services
Starts existing containers for a service
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| Name | Type | Default | Description |
|:------------|:-------|:--------|:--------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
<!---MARKER_GEN_END-->

View File

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

View File

@@ -1,14 +1,14 @@
# docker compose stop
<!---MARKER_GEN_START-->
Stop services
Stops running containers without removing them. They can be started again with `docker compose start`.
### Options
| Name | Type | Default | Description |
|:------------------|:------|:--------|:--------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |
| Name | Type | Default | Description |
|:------------------|:-------|:--------|:--------------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `-t`, `--timeout` | `int` | `0` | Specify a shutdown timeout in seconds |
<!---MARKER_GEN_END-->

View File

@@ -1,13 +1,13 @@
# docker compose top
<!---MARKER_GEN_START-->
Display the running processes
Displays the running processes
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| Name | Type | Default | Description |
|:------------|:-------|:--------|:--------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
<!---MARKER_GEN_END-->

View File

@@ -1,13 +1,13 @@
# docker compose unpause
<!---MARKER_GEN_START-->
Unpause services
Unpauses paused containers of a service
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:--------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| Name | Type | Default | Description |
|:------------|:-------|:--------|:--------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
<!---MARKER_GEN_END-->

View File

@@ -1,40 +1,58 @@
# docker compose up
<!---MARKER_GEN_START-->
Create and start containers
Builds, (re)creates, starts, and attaches to containers for a service.
Unless they are already running, this command also starts any linked services.
The `docker compose up` command aggregates the output of each container (like `docker compose logs --follow` does).
One can optionally select a subset of services to attach to using `--attach` flag, or exclude some services using
`--no-attach` to prevent output to be flooded by some verbose services.
When the command exits, all containers are stopped. Running `docker compose up --detach` starts the containers in the
background and leaves them running.
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
(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 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`.
### Options
| Name | Type | Default | Description |
|:-------------------------------|:--------------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------------------|
| `--abort-on-container-exit` | | | Stops all containers if any container was stopped. Incompatible with -d |
| `--abort-on-container-failure` | | | Stops all containers if any container exited with failure. Incompatible with -d |
| `--always-recreate-deps` | | | Recreate dependent containers. Incompatible with --no-recreate. |
| `--abort-on-container-exit` | `bool` | | Stops all containers if any container was stopped. Incompatible with -d |
| `--abort-on-container-failure` | `bool` | | Stops all containers if any container exited with failure. Incompatible with -d |
| `--always-recreate-deps` | `bool` | | Recreate dependent containers. Incompatible with --no-recreate. |
| `--attach` | `stringArray` | | Restrict attaching to the specified services. Incompatible with --attach-dependencies. |
| `--attach-dependencies` | | | Automatically attach to log output of dependent services |
| `--build` | | | Build images before starting containers |
| `-d`, `--detach` | | | Detached mode: Run containers in the background |
| `--dry-run` | | | Execute command in dry run mode |
| `--attach-dependencies` | `bool` | | Automatically attach to log output of dependent services |
| `--build` | `bool` | | Build images before starting containers |
| `-d`, `--detach` | `bool` | | Detached mode: Run containers in the background |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--exit-code-from` | `string` | | Return the exit code of the selected service container. Implies --abort-on-container-exit |
| `--force-recreate` | | | Recreate containers even if their configuration and image haven't changed |
| `--menu` | | | Enable interactive shortcuts when running attached. Incompatible with --detach. Can also be enable/disable by setting COMPOSE_MENU environment var. |
| `--force-recreate` | `bool` | | Recreate containers even if their configuration and image haven't changed |
| `--menu` | `bool` | | Enable interactive shortcuts when running attached. Incompatible with --detach. Can also be enable/disable by setting COMPOSE_MENU environment var. |
| `--no-attach` | `stringArray` | | Do not attach (stream logs) to the specified services |
| `--no-build` | | | Don't build an image, even if it's policy |
| `--no-color` | | | Produce monochrome output |
| `--no-deps` | | | Don't start linked services |
| `--no-log-prefix` | | | Don't print prefix in logs |
| `--no-recreate` | | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
| `--no-start` | | | Don't start the services after creating them |
| `--no-build` | `bool` | | Don't build an image, even if it's policy |
| `--no-color` | `bool` | | Produce monochrome output |
| `--no-deps` | `bool` | | Don't start linked services |
| `--no-log-prefix` | `bool` | | Don't print prefix in logs |
| `--no-recreate` | `bool` | | If containers already exist, don't recreate them. Incompatible with --force-recreate. |
| `--no-start` | `bool` | | Don't start the services after creating them |
| `--pull` | `string` | `policy` | Pull image before running ("always"\|"missing"\|"never") |
| `--quiet-pull` | | | Pull without printing progress information |
| `--remove-orphans` | | | Remove containers for services not defined in the Compose file |
| `-V`, `--renew-anon-volumes` | | | Recreate anonymous volumes instead of retrieving data from the previous containers |
| `--quiet-pull` | `bool` | | Pull without printing progress information |
| `--remove-orphans` | `bool` | | Remove containers for services not defined in the Compose file |
| `-V`, `--renew-anon-volumes` | `bool` | | Recreate anonymous volumes instead of retrieving data from the previous containers |
| `--scale` | `stringArray` | | Scale SERVICE to NUM instances. Overrides the `scale` setting in the Compose file if present. |
| `-t`, `--timeout` | `int` | `0` | Use this timeout in seconds for container shutdown when attached or when containers are already running |
| `--timestamps` | | | Show timestamps |
| `--wait` | | | Wait for services to be running\|healthy. Implies detached mode. |
| `--timestamps` | `bool` | | Show timestamps |
| `--wait` | `bool` | | Wait for services to be running\|healthy. Implies detached mode. |
| `--wait-timeout` | `int` | `0` | Maximum duration to wait for the project to be running\|healthy |
| `-w`, `--watch` | | | Watch source code and rebuild/refresh containers when files are updated. |
| `-w`, `--watch` | `bool` | | Watch source code and rebuild/refresh containers when files are updated. |
<!---MARKER_GEN_END-->

View File

@@ -7,9 +7,9 @@ Show the Docker Compose version information
| Name | Type | Default | Description |
|:-----------------|:---------|:--------|:---------------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `-f`, `--format` | `string` | | Format the output. Values: [pretty \| json]. (Default: pretty) |
| `--short` | | | Shows only Compose's version number |
| `--short` | `bool` | | Shows only Compose's version number |
<!---MARKER_GEN_END-->

View File

@@ -5,10 +5,10 @@ Block until the first service container stops
### Options
| Name | Type | Default | Description |
|:-----------------|:-----|:--------|:---------------------------------------------|
| `--down-project` | | | Drops project when the first container stops |
| `--dry-run` | | | Execute command in dry run mode |
| Name | Type | Default | Description |
|:-----------------|:-------|:--------|:---------------------------------------------|
| `--down-project` | `bool` | | Drops project when the first container stops |
| `--dry-run` | `bool` | | Execute command in dry run mode |
<!---MARKER_GEN_END-->

View File

@@ -5,11 +5,12 @@ Watch build context for service and rebuild/refresh containers when files are up
### Options
| Name | Type | Default | Description |
|:------------|:-----|:--------|:----------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--no-up` | | | Do not build & start services before watching |
| `--quiet` | | | hide build output |
| Name | Type | Default | Description |
|:------------|:-------|:--------|:----------------------------------------------|
| `--dry-run` | `bool` | | Execute command in dry run mode |
| `--no-up` | `bool` | | Do not build & start services before watching |
| `--prune` | `bool` | | Prune dangling images on rebuild |
| `--quiet` | `bool` | | hide build output |
<!---MARKER_GEN_END-->

View File

@@ -306,7 +306,7 @@ options:
- option: progress
value_type: string
default_value: auto
description: Set type of progress output (auto, tty, plain, quiet)
description: Set type of progress output (auto, tty, plain, json, quiet)
deprecated: false
hidden: false
experimental: false

View File

@@ -99,7 +99,7 @@ options:
- option: progress
value_type: string
default_value: auto
description: Set type of ui output (auto, tty, plain, quiet)
description: Set type of ui output (auto, tty, plain, json, quiet)
deprecated: false
hidden: true
experimental: false

View File

@@ -4,7 +4,7 @@ long: |-
Forces running containers to stop by sending a `SIGKILL` signal. Optionally the signal can be passed, for example:
```console
$ docker-compose kill -s SIGINT
$ docker compose kill -s SIGINT
```
usage: docker compose kill [OPTIONS] [SERVICE...]
pname: docker compose

View File

@@ -17,6 +17,16 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: prune
value_type: bool
default_value: "false"
description: Prune dangling images on rebuild
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: quiet
value_type: bool
default_value: "false"

View File

@@ -48,7 +48,21 @@ func generateDocs(opts *options) error {
if err != nil {
return err
}
return tool.GenAllTree()
for _, format := range opts.formats {
switch format {
case "yaml":
if err := tool.GenYamlTree(cmd); err != nil {
return err
}
case "md":
if err := tool.GenMarkdownTree(cmd); err != nil {
return err
}
default:
return fmt.Errorf("unknown format %q", format)
}
}
return nil
}
func disableFlagsInUseLine(cmd *cobra.Command) {
@@ -69,15 +83,17 @@ func visitAll(root *cobra.Command, fn func(*cobra.Command)) {
}
type options struct {
source string
target string
source string
target string
formats []string
}
func main() {
cwd, _ := os.Getwd()
opts := &options{
source: filepath.Join(cwd, "docs", "reference"),
target: filepath.Join(cwd, "docs", "reference"),
source: filepath.Join(cwd, "docs", "reference"),
target: filepath.Join(cwd, "docs", "reference"),
formats: []string{"yaml", "md"},
}
fmt.Printf("Project root: %s\n", opts.source)
fmt.Printf("Generating yaml files into %s\n", opts.target)

68
go.mod
View File

@@ -1,21 +1,23 @@
module github.com/docker/compose/v2
go 1.21
go 1.21.0
toolchain go1.22.2
require (
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/Microsoft/go-winio v0.6.2
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/buger/goterm v1.0.4
github.com/compose-spec/compose-go/v2 v2.1.2
github.com/containerd/console v1.0.4
github.com/containerd/containerd v1.7.18
github.com/compose-spec/compose-go/v2 v2.1.6
github.com/containerd/containerd v1.7.20
github.com/containerd/platforms v0.2.1
github.com/davecgh/go-spew v1.1.1
github.com/distribution/reference v0.6.0
github.com/docker/buildx v0.15.0
github.com/docker/cli v26.1.4+incompatible
github.com/docker/cli-docs-tool v0.7.0
github.com/docker/docker v26.1.4+incompatible
github.com/docker/buildx v0.16.2
github.com/docker/cli v27.1.2+incompatible
github.com/docker/cli-docs-tool v0.8.0
github.com/docker/docker v27.1.2+incompatible
github.com/docker/go-connections v0.5.0
github.com/docker/go-units v0.5.0
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203
@@ -27,7 +29,7 @@ require (
github.com/mattn/go-shellwords v1.0.12
github.com/mitchellh/go-ps v1.0.0
github.com/mitchellh/mapstructure v1.5.0
github.com/moby/buildkit v0.14.0
github.com/moby/buildkit v0.15.1
github.com/moby/patternmatcher v0.6.0
github.com/moby/term v0.5.0
github.com/morikuni/aec v1.0.0
@@ -37,7 +39,7 @@ require (
github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc
github.com/sirupsen/logrus v1.9.3
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/spf13/cobra v1.8.0
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
github.com/theupdateframework/notary v0.7.0
@@ -53,8 +55,8 @@ require (
go.uber.org/mock v0.4.0
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3
golang.org/x/sync v0.7.0
golang.org/x/sys v0.21.0
google.golang.org/grpc v1.59.0
golang.org/x/sys v0.22.0
google.golang.org/grpc v1.60.1
gopkg.in/yaml.v3 v3.0.1
gotest.tools/v3 v3.5.1
)
@@ -64,7 +66,6 @@ require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Microsoft/hcsshim v0.11.5 // indirect
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
github.com/aws/aws-sdk-go-v2/config v1.26.6 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
@@ -81,26 +82,28 @@ require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/console v1.0.4 // indirect
github.com/containerd/containerd/api v1.7.19 // indirect
github.com/containerd/continuity v0.4.3 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/containerd/ttrpc v1.2.4 // indirect
github.com/containerd/ttrpc v1.2.5 // indirect
github.com/containerd/typeurl/v2 v2.1.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/docker/docker-credential-helpers v0.8.2 // indirect
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fvbommel/sortorder v1.0.2 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-viper/mapstructure/v2 v2.0.0 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
@@ -119,7 +122,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/compress v1.17.4 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
@@ -127,8 +130,7 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/spdystream v0.2.0 // indirect
@@ -137,6 +139,7 @@ require (
github.com/moby/sys/signal v0.7.0 // indirect
github.com/moby/sys/symlink v0.2.0 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
@@ -147,12 +150,14 @@ require (
github.com/prometheus/client_golang v1.17.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect
github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b // indirect
github.com/shibumi/go-pathspec v1.3.0 // indirect
github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c // indirect
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
@@ -161,21 +166,20 @@ require (
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.21.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/oauth2 v0.11.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect

144
go.sum
View File

@@ -1,8 +1,7 @@
cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME=
cloud.google.com/go/compute v1.23.1 h1:V97tBoDaZHb6leicZ1G6DLK2BAaZLJ/7+9BB/En3hR0=
cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y=
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
@@ -19,8 +18,8 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
github.com/Microsoft/hcsshim v0.11.5 h1:haEcLNpj9Ka1gd3B3tAEs9CpE0c+1IhoL59w/exYU38=
github.com/Microsoft/hcsshim v0.11.5/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ=
github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2 h1:+vx7roKuyA63nhn5WAunQHLTznkw5W8b1Xc0dNjp83s=
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2/go.mod h1:HBCaDeC1lPdgDeDbhX8XFpy1jqjK0IBG8W5K+xYqA0w=
github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
@@ -86,14 +85,16 @@ github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+g
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/compose-spec/compose-go/v2 v2.1.2 h1:N2XmNYg5jHNBaU+4/zSAe2UrZLq7Kkp1eSsOHfAHbxQ=
github.com/compose-spec/compose-go/v2 v2.1.2/go.mod h1:NJGRGazJfh0tD7d13h66KDVvyOHK49Wil2CIhoffiD0=
github.com/compose-spec/compose-go/v2 v2.1.6 h1:d0Cs0DffmOwmSzs0YPHwKCskknGq2jfGg4uGowlEpps=
github.com/compose-spec/compose-go/v2 v2.1.6/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao=
github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4=
github.com/containerd/containerd v1.7.20 h1:Sl6jQYk3TRavaU83h66QMbI2Nqg9Jm6qzwX57Vsn1SQ=
github.com/containerd/containerd v1.7.20/go.mod h1:52GsS5CwquuqPuLncsXwG0t2CiUce+KsNHJZQJvAgR0=
github.com/containerd/containerd/api v1.7.19 h1:VWbJL+8Ap4Ju2mx9c9qS1uFSB1OVYr5JJrW2yT5vFoA=
github.com/containerd/containerd/api v1.7.19/go.mod h1:fwGavl3LNwAV5ilJ0sbrABL44AQxmNjDRcwheXDb6Ig=
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8=
github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
@@ -109,11 +110,12 @@ github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7np
github.com/containerd/stargz-snapshotter v0.15.1 h1:fpsP4kf/Z4n2EYnU0WT8ZCE3eiKDwikDhL6VwxIlgeA=
github.com/containerd/stargz-snapshotter/estargz v0.15.1 h1:eXJjw9RbkLFgioVaTG+G/ZW/0kEe2oEKCdS/ZxIyoCU=
github.com/containerd/stargz-snapshotter/estargz v0.15.1/go.mod h1:gr2RNwukQ/S9Nv33Lt6UC7xEx58C+LHRdoqbEKjz1Kk=
github.com/containerd/ttrpc v1.2.4 h1:eQCQK4h9dxDmpOb9QOOMh2NHTfzroH1IkmHiKZi05Oo=
github.com/containerd/ttrpc v1.2.4/go.mod h1:ojvb8SJBSch0XkqNO0L0YX/5NxR3UnVk2LzFKBK0upc=
github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU=
github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4=
github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.17/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
@@ -124,19 +126,19 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/docker/buildx v0.15.0 h1:PVq4IMnTvw1Sx0RKDWbfi2eTGawFd9CMBYnz9xat93Y=
github.com/docker/buildx v0.15.0/go.mod h1:AdkB1RIcU4rfZ6mpw2PA2pOi1ppI9yvFXkVEpq5EmS4=
github.com/docker/cli v26.1.4+incompatible h1:I8PHdc0MtxEADqYJZvhBrW9bo8gawKwwenxRM7/rLu8=
github.com/docker/cli v26.1.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.7.0 h1:M2Da98Unz2kz3A5d4yeSGbhyOge2mfYSNjAFt01Rw0M=
github.com/docker/cli-docs-tool v0.7.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o=
github.com/docker/buildx v0.16.2 h1:SPcyEiiCZEntJQ+V0lJI8ZudUrki2v1qUqmC/NqxDDs=
github.com/docker/buildx v0.16.2/go.mod h1:by+CuE4Q+2NvECkIhNcWe89jjbHADCrDlzS9MRgbv2k=
github.com/docker/cli v27.1.2+incompatible h1:nYviRv5Y+YAKx3dFrTvS1ErkyVVunKOhoweCTE1BsnI=
github.com/docker/cli v27.1.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.8.0 h1:YcDWl7rQJC3lJ7WVZRwSs3bc9nka97QLWfyJQli8yJU=
github.com/docker/cli-docs-tool v0.8.0/go.mod h1:8TQQ3E7mOXoYUs811LiPdUnAhXrcVsBIrW21a5pUbdk=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v26.1.4+incompatible h1:vuTpXDuoga+Z38m1OZHzl7NKisKWaWlhjQk7IDPSLsU=
github.com/docker/docker v26.1.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
github.com/docker/docker v27.1.2+incompatible h1:AhGzR1xaQIy53qCkxARaFluI00WPGtXn0AJuoQsVYTY=
github.com/docker/docker v27.1.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo=
github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
@@ -170,8 +172,9 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
@@ -187,8 +190,8 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc=
github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -219,8 +222,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk=
github.com/google/pprof v0.0.0-20230323073829-e72429f035bd/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
@@ -273,8 +276,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -311,17 +314,15 @@ github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyex
github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/buildkit v0.14.0 h1:mHv2lFS8znLDRc4SMyM2B9tPjxWh2blMvr0H7ARquNM=
github.com/moby/buildkit v0.14.0/go.mod h1:1XssG7cAqv5Bz1xcGMxJL123iCv5TYN4Z/qf647gfuk=
github.com/moby/buildkit v0.15.1 h1:J6wrew7hphKqlq1wuu6yaUb/1Ra7gEzDAovylGztAKM=
github.com/moby/buildkit v0.15.1/go.mod h1:Yis8ZMUJTHX9XhH9zVyK2igqSHV3sxi3UN0uztZocZk=
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@@ -340,6 +341,8 @@ github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZ
github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs=
github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg=
github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU=
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -372,8 +375,8 @@ github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3I
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk=
github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
@@ -410,14 +413,15 @@ github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc h1:zAsgcP8MhzAbhMnB1QQ2O7ZhWYVGYSR2iVcjzQuPV+o=
github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc/go.mod h1:S8xSOnV3CgpNrWd0GQ/OoQfMtlg2uPRSuTzcSGrzwK8=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE=
github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs=
@@ -437,8 +441,8 @@ github.com/spdx/tools-golang v0.5.3/go.mod h1:/ETOahiAo96Ob0/RAIBmFZw6XN0yTnyr/u
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94 h1:JmfC365KywYwHB946TTiQWEb8kqPY+pybPLoGE9GgVk=
github.com/spf13/cast v0.0.0-20150508191742-4d07383ffe94/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cobra v0.0.1/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431 h1:XTHrT015sxHyJ5FnQ0AeemSspZWaDq7DoTRW0EVsDCE=
github.com/spf13/jwalterweatherman v0.0.0-20141219030609-3d60171a6431/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.0/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -468,6 +472,8 @@ github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8
github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375/go.mod h1:xRroudyp5iVtxKqZCrA6n2TLFRBf8bmnjr1UD4x+z7g=
github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c h1:+6wg/4ORAbnSoGDzg2Q1i3CeMcT/jjhye/ZfnBHy7/M=
github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c/go.mod h1:vbbYqJlnswsbJqWUcJN8fKtBhnEgldDrcagTgnBVKKM=
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8=
github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4/go.mod h1:278M4p8WsNh3n4a1eqiFcV2FGk7wE5fwUpUom9mK9lE=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=
github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Qb2z5hI1UHxSQt4JMyxebFR15KnApw=
@@ -496,8 +502,8 @@ go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0 h1:jd0+5t/YynESZqsSyPz+7PAFdEop0dlN0+PkyHYo8oI=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.44.0/go.mod h1:U707O40ee1FpQGyhvqnzmCJm1Wh6OX6GGBVn0E6Uyyk=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw=
@@ -528,8 +534,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -540,7 +546,6 @@ golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -548,10 +553,10 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -582,20 +587,19 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -609,17 +613,15 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA=
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI=
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b h1:CIC2YMXmIhYw6evmhPxBKJ4fmLbOFtXQN/GV3XOZR8k=
google.golang.org/genproto/googleapis/api v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:IBQ646DjkDkvUIsVq/cc03FUFQ9wbZu7yE396YcL870=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc=
google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg=
google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic=
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f h1:2yNACc1O40tTnrsbk9Cv6oxiW8pxI/pXj0wRtdlYmgY=
google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA=
google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU=
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=

View File

@@ -121,6 +121,7 @@ const WatchLogger = "#watch"
type WatchOptions struct {
Build *BuildOptions
LogTo LogConsumer
Prune bool
}
// BuildOptions group options of the Build API

View File

@@ -107,7 +107,8 @@ func (d *DryRunClient) ContainerCreate(ctx context.Context, config *containerTyp
Names: []string{containerName},
Labels: config.Labels,
HostConfig: struct {
NetworkMode string `json:",omitempty"`
NetworkMode string `json:",omitempty"`
Annotations map[string]string `json:",omitempty"`
}{},
})
return containerType.CreateResponse{ID: containerName}, nil
@@ -188,15 +189,15 @@ func (d *DryRunClient) ContainerUnpause(ctx context.Context, container string) e
return nil
}
func (d *DryRunClient) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, moby.ContainerPathStat, error) {
func (d *DryRunClient) CopyFromContainer(ctx context.Context, container, srcPath string) (io.ReadCloser, containerType.PathStat, error) {
rc := io.NopCloser(strings.NewReader(""))
if _, err := d.ContainerStatPath(ctx, container, srcPath); err != nil {
return rc, moby.ContainerPathStat{}, fmt.Errorf(" %s Could not find the file %s in container %s", DRYRUN_PREFIX, srcPath, container)
return rc, containerType.PathStat{}, fmt.Errorf(" %s Could not find the file %s in container %s", DRYRUN_PREFIX, srcPath, container)
}
return rc, moby.ContainerPathStat{}, nil
return rc, containerType.PathStat{}, nil
}
func (d *DryRunClient) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options moby.CopyToContainerOptions) error {
func (d *DryRunClient) CopyToContainer(ctx context.Context, container, path string, content io.Reader, options containerType.CopyToContainerOptions) error {
if _, err := d.ContainerStatPath(ctx, container, path); err != nil {
return fmt.Errorf(" %s Could not find the file %s in container %s", DRYRUN_PREFIX, path, container)
}
@@ -269,8 +270,8 @@ func (d *DryRunClient) NetworkConnect(ctx context.Context, networkName, containe
return nil
}
func (d *DryRunClient) NetworkCreate(ctx context.Context, name string, options moby.NetworkCreate) (moby.NetworkCreateResponse, error) {
return moby.NetworkCreateResponse{
func (d *DryRunClient) NetworkCreate(ctx context.Context, name string, options network.CreateOptions) (network.CreateResponse, error) {
return network.CreateResponse{
ID: name,
Warning: "",
}, nil
@@ -298,7 +299,7 @@ func (d *DryRunClient) VolumeRemove(ctx context.Context, volumeID string, force
return nil
}
func (d *DryRunClient) ContainerExecCreate(ctx context.Context, container string, config moby.ExecConfig) (moby.IDResponse, error) {
func (d *DryRunClient) ContainerExecCreate(ctx context.Context, container string, config containerType.ExecOptions) (moby.IDResponse, error) {
b := make([]byte, 32)
_, _ = rand.Read(b)
id := fmt.Sprintf("%x", b)
@@ -311,7 +312,7 @@ func (d *DryRunClient) ContainerExecCreate(ctx context.Context, container string
}, nil
}
func (d *DryRunClient) ContainerExecStart(ctx context.Context, execID string, config moby.ExecStartCheck) error {
func (d *DryRunClient) ContainerExecStart(ctx context.Context, execID string, config containerType.ExecStartOptions) error {
v, ok := d.execs.LoadAndDelete(execID)
if !ok {
return fmt.Errorf("invalid exec ID %q", execID)
@@ -351,11 +352,11 @@ func (d *DryRunClient) ContainerDiff(ctx context.Context, container string) ([]c
return d.apiClient.ContainerDiff(ctx, container)
}
func (d *DryRunClient) ContainerExecAttach(ctx context.Context, execID string, config moby.ExecStartCheck) (moby.HijackedResponse, error) {
func (d *DryRunClient) ContainerExecAttach(ctx context.Context, execID string, config containerType.ExecStartOptions) (moby.HijackedResponse, error) {
return moby.HijackedResponse{}, errors.New("interactive exec is not supported in dry-run mode")
}
func (d *DryRunClient) ContainerExecInspect(ctx context.Context, execID string) (moby.ContainerExecInspect, error) {
func (d *DryRunClient) ContainerExecInspect(ctx context.Context, execID string) (containerType.ExecInspect, error) {
return d.apiClient.ContainerExecInspect(ctx, execID)
}
@@ -379,15 +380,15 @@ func (d *DryRunClient) ContainerResize(ctx context.Context, container string, op
return d.apiClient.ContainerResize(ctx, container, options)
}
func (d *DryRunClient) ContainerStatPath(ctx context.Context, container, path string) (moby.ContainerPathStat, error) {
func (d *DryRunClient) ContainerStatPath(ctx context.Context, container, path string) (containerType.PathStat, error) {
return d.apiClient.ContainerStatPath(ctx, container, path)
}
func (d *DryRunClient) ContainerStats(ctx context.Context, container string, stream bool) (moby.ContainerStats, error) {
func (d *DryRunClient) ContainerStats(ctx context.Context, container string, stream bool) (containerType.StatsResponseReader, error) {
return d.apiClient.ContainerStats(ctx, container, stream)
}
func (d *DryRunClient) ContainerStatsOneShot(ctx context.Context, container string) (moby.ContainerStats, error) {
func (d *DryRunClient) ContainerStatsOneShot(ctx context.Context, container string) (containerType.StatsResponseReader, error) {
return d.apiClient.ContainerStatsOneShot(ctx, container)
}
@@ -403,7 +404,7 @@ func (d *DryRunClient) ContainerWait(ctx context.Context, container string, cond
return d.apiClient.ContainerWait(ctx, container, condition)
}
func (d *DryRunClient) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (moby.ContainersPruneReport, error) {
func (d *DryRunClient) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (containerType.PruneReport, error) {
return d.apiClient.ContainersPrune(ctx, pruneFilters)
}
@@ -427,7 +428,7 @@ func (d *DryRunClient) ImageHistory(ctx context.Context, imageName string) ([]im
return d.apiClient.ImageHistory(ctx, imageName)
}
func (d *DryRunClient) ImageImport(ctx context.Context, source moby.ImageImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error) {
func (d *DryRunClient) ImageImport(ctx context.Context, source image.ImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error) {
return d.apiClient.ImageImport(ctx, source, ref, options)
}
@@ -435,11 +436,11 @@ func (d *DryRunClient) ImageList(ctx context.Context, options image.ListOptions)
return d.apiClient.ImageList(ctx, options)
}
func (d *DryRunClient) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (moby.ImageLoadResponse, error) {
func (d *DryRunClient) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (image.LoadResponse, error) {
return d.apiClient.ImageLoad(ctx, input, quiet)
}
func (d *DryRunClient) ImageSearch(ctx context.Context, term string, options moby.ImageSearchOptions) ([]registry.SearchResult, error) {
func (d *DryRunClient) ImageSearch(ctx context.Context, term string, options registry.SearchOptions) ([]registry.SearchResult, error) {
return d.apiClient.ImageSearch(ctx, term, options)
}
@@ -451,7 +452,7 @@ func (d *DryRunClient) ImageTag(ctx context.Context, imageName, ref string) erro
return d.apiClient.ImageTag(ctx, imageName, ref)
}
func (d *DryRunClient) ImagesPrune(ctx context.Context, pruneFilter filters.Args) (moby.ImagesPruneReport, error) {
func (d *DryRunClient) ImagesPrune(ctx context.Context, pruneFilter filters.Args) (image.PruneReport, error) {
return d.apiClient.ImagesPrune(ctx, pruneFilter)
}
@@ -471,19 +472,19 @@ func (d *DryRunClient) NodeUpdate(ctx context.Context, nodeID string, version sw
return d.apiClient.NodeUpdate(ctx, nodeID, version, node)
}
func (d *DryRunClient) NetworkInspect(ctx context.Context, networkName string, options moby.NetworkInspectOptions) (moby.NetworkResource, error) {
func (d *DryRunClient) NetworkInspect(ctx context.Context, networkName string, options network.InspectOptions) (network.Inspect, error) {
return d.apiClient.NetworkInspect(ctx, networkName, options)
}
func (d *DryRunClient) NetworkInspectWithRaw(ctx context.Context, networkName string, options moby.NetworkInspectOptions) (moby.NetworkResource, []byte, error) {
func (d *DryRunClient) NetworkInspectWithRaw(ctx context.Context, networkName string, options network.InspectOptions) (network.Inspect, []byte, error) {
return d.apiClient.NetworkInspectWithRaw(ctx, networkName, options)
}
func (d *DryRunClient) NetworkList(ctx context.Context, options moby.NetworkListOptions) ([]moby.NetworkResource, error) {
func (d *DryRunClient) NetworkList(ctx context.Context, options network.ListOptions) ([]network.Inspect, error) {
return d.apiClient.NetworkList(ctx, options)
}
func (d *DryRunClient) NetworksPrune(ctx context.Context, pruneFilter filters.Args) (moby.NetworksPruneReport, error) {
func (d *DryRunClient) NetworksPrune(ctx context.Context, pruneFilter filters.Args) (network.PruneReport, error) {
return d.apiClient.NetworksPrune(ctx, pruneFilter)
}
@@ -611,7 +612,7 @@ func (d *DryRunClient) SecretUpdate(ctx context.Context, id string, version swar
return d.apiClient.SecretUpdate(ctx, id, version, secret)
}
func (d *DryRunClient) Events(ctx context.Context, options moby.EventsOptions) (<-chan events.Message, <-chan error) {
func (d *DryRunClient) Events(ctx context.Context, options events.ListOptions) (<-chan events.Message, <-chan error) {
return d.apiClient.Events(ctx, options)
}
@@ -643,7 +644,7 @@ func (d *DryRunClient) VolumeList(ctx context.Context, opts volume.ListOptions)
return d.apiClient.VolumeList(ctx, opts)
}
func (d *DryRunClient) VolumesPrune(ctx context.Context, pruneFilter filters.Args) (moby.VolumesPruneReport, error) {
func (d *DryRunClient) VolumesPrune(ctx context.Context, pruneFilter filters.Args) (volume.PruneReport, error) {
return d.apiClient.VolumesPrune(ctx, pruneFilter)
}

View File

@@ -17,13 +17,11 @@
package api
import (
"io"
"github.com/docker/cli/cli/streams"
)
type Streams interface {
Out() *streams.Out
Err() io.Writer
Err() *streams.Out
In() *streams.In
}

View File

@@ -23,10 +23,8 @@ import (
"os"
"path/filepath"
"github.com/moby/buildkit/util/progress/progressui"
"github.com/compose-spec/compose-go/v2/types"
"github.com/containerd/containerd/platforms"
"github.com/containerd/platforms"
"github.com/docker/buildx/build"
"github.com/docker/buildx/builder"
"github.com/docker/buildx/controller/pb"
@@ -39,14 +37,15 @@ import (
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/builder/remotecontext/urlutil"
"github.com/docker/go-units"
bclient "github.com/moby/buildkit/client"
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/session/auth/authprovider"
"github.com/moby/buildkit/session/secrets/secretsprovider"
"github.com/moby/buildkit/session/sshforward/sshprovider"
"github.com/moby/buildkit/util/entitlements"
"github.com/moby/buildkit/util/progress/progressui"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
@@ -448,9 +447,9 @@ func (s *composeService) toBuildOptions(project *types.Project, service types.Se
}
func toUlimitOpt(ulimits map[string]*types.UlimitsConfig) *cliopts.UlimitOpt {
ref := map[string]*units.Ulimit{}
ref := map[string]*container.Ulimit{}
for _, limit := range toUlimits(ulimits) {
ref[limit.Name] = &units.Ulimit{
ref[limit.Name] = &container.Ulimit{
Name: limit.Name,
Hard: limit.Hard,
Soft: limit.Soft,

View File

@@ -20,7 +20,6 @@ import (
"context"
"errors"
"fmt"
"io"
"os"
"strconv"
"strings"
@@ -28,6 +27,7 @@ import (
"github.com/docker/compose/v2/internal/desktop"
"github.com/docker/compose/v2/internal/experimental"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/volume"
"github.com/jonboulle/clockwork"
@@ -128,11 +128,11 @@ func (s *composeService) stdin() *streams.In {
return s.dockerCli.In()
}
func (s *composeService) stderr() io.Writer {
func (s *composeService) stderr() *streams.Out {
return s.dockerCli.Err()
}
func (s *composeService) stdinfo() io.Writer {
func (s *composeService) stdinfo() *streams.Out {
if stdioToStdout {
return s.dockerCli.Out()
}
@@ -261,7 +261,7 @@ func (s *composeService) actualVolumes(ctx context.Context, projectName string)
}
func (s *composeService) actualNetworks(ctx context.Context, projectName string) (types.Networks, error) {
networks, err := s.apiClient().NetworkList(ctx, moby.NetworkListOptions{
networks, err := s.apiClient().NetworkList(ctx, network.ListOptions{
Filters: filters.NewArgs(projectFilter(projectName)),
})
if err != nil {

View File

@@ -93,10 +93,19 @@ func (s *composeService) getSpecifiedContainer(ctx context.Context, projectName
}
return moby.Container{}, fmt.Errorf("service %q is not running", serviceName)
}
// Sort by container number first, then put one-off containers at the end
sort.Slice(containers, func(i, j int) bool {
x, _ := strconv.Atoi(containers[i].Labels[api.ContainerNumberLabel])
y, _ := strconv.Atoi(containers[j].Labels[api.ContainerNumberLabel])
return x < y
numberLabelX, _ := strconv.Atoi(containers[i].Labels[api.ContainerNumberLabel])
numberLabelY, _ := strconv.Atoi(containers[j].Labels[api.ContainerNumberLabel])
IsOneOffLabelTrueX := containers[i].Labels[api.OneoffLabel] == "True"
IsOneOffLabelTrueY := containers[j].Labels[api.OneoffLabel] == "True"
if numberLabelX == numberLabelY {
return !IsOneOffLabelTrueX && IsOneOffLabelTrueY
}
return numberLabelX < numberLabelY
})
container := containers[0]
return container, nil
@@ -118,17 +127,16 @@ func isRunning() containerPredicate {
}
}
func isNotService(services ...string) containerPredicate {
return func(c moby.Container) bool {
service := c.Labels[api.ServiceLabel]
return !utils.StringContains(services, service)
}
}
// isOrphaned is a predicate to select containers without a matching service definition in compose project
func isOrphaned(project *types.Project) containerPredicate {
services := append(project.ServiceNames(), project.DisabledServiceNames()...)
return func(c moby.Container) bool {
// One-off container
v, ok := c.Labels[api.OneoffLabel]
if ok && v == "True" {
return c.State == ContainerExited || c.State == ContainerDead
}
// Service that is not defined in the compose model
service := c.Labels[api.ServiceLabel]
return !utils.StringContains(services, service)
}

View File

@@ -30,7 +30,7 @@ import (
"go.opentelemetry.io/otel/trace"
"github.com/compose-spec/compose-go/v2/types"
"github.com/containerd/containerd/platforms"
"github.com/containerd/platforms"
"github.com/docker/compose/v2/internal/tracing"
moby "github.com/docker/docker/api/types"
containerType "github.com/docker/docker/api/types/container"

View File

@@ -30,7 +30,7 @@ import (
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/pkg/api"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/system"
)
@@ -88,9 +88,9 @@ func (s *composeService) copy(ctx context.Context, projectName string, options a
w := progress.ContextWriter(ctx)
g := errgroup.Group{}
for _, cont := range containers {
container := cont
ctr := cont
g.Go(func() error {
name := getCanonicalContainerName(container)
name := getCanonicalContainerName(ctr)
var msg string
if direction == fromService {
msg = fmt.Sprintf("copy %s:%s to %s", name, srcPath, dstPath)
@@ -103,7 +103,7 @@ func (s *composeService) copy(ctx context.Context, projectName string, options a
Status: progress.Working,
StatusText: "Copying",
})
if err := copyFunc(ctx, container.ID, srcPath, dstPath, options); err != nil {
if err := copyFunc(ctx, ctr.ID, srcPath, dstPath, options); err != nil {
return err
}
w.Event(progress.Event{
@@ -124,11 +124,11 @@ func (s *composeService) listContainersTargetedForCopy(ctx context.Context, proj
var err error
switch {
case index > 0:
container, err := s.getSpecifiedContainer(ctx, projectName, oneOffExclude, true, serviceName, index)
ctr, err := s.getSpecifiedContainer(ctx, projectName, oneOffExclude, true, serviceName, index)
if err != nil {
return nil, err
}
return append(containers, container), nil
return append(containers, ctr), nil
default:
containers, err = s.getContainers(ctx, projectName, oneOffExclude, true, serviceName)
if err != nil {
@@ -237,7 +237,7 @@ func (s *composeService) copyToContainer(ctx context.Context, containerID string
}
}
options := moby.CopyToContainerOptions{
options := container.CopyToContainerOptions{
AllowOverwriteDirWithFile: false,
CopyUIDGID: opts.CopyUIDGID,
}
@@ -304,7 +304,7 @@ func (s *composeService) copyFromContainer(ctx context.Context, containerID, src
return archive.CopyTo(preArchive, srcInfo, dstPath)
}
func splitCpArg(arg string) (container, path string) {
func splitCpArg(arg string) (ctr, path string) {
if system.IsAbs(arg) {
// Explicit local absolute path, e.g., `C:\foo` or `/foo`.
return "", arg

View File

@@ -33,6 +33,9 @@ import (
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/compose/v2/internal/desktop"
pathutil "github.com/docker/compose/v2/internal/paths"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/blkiodev"
"github.com/docker/docker/api/types/container"
@@ -41,15 +44,10 @@ import (
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/strslice"
"github.com/docker/docker/api/types/versions"
volume_api "github.com/docker/docker/api/types/volume"
volumetypes "github.com/docker/docker/api/types/volume"
"github.com/docker/docker/errdefs"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
"github.com/sirupsen/logrus"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"
)
type createOptions struct {
@@ -103,8 +101,7 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt
return err
}
allServiceNames := append(project.ServiceNames(), project.DisabledServiceNames()...)
orphans := observedState.filter(isNotService(allServiceNames...))
orphans := observedState.filter(isOrphaned(project))
if len(orphans) > 0 && !options.IgnoreOrphans {
if options.RemoveOrphans {
err := s.removeContainers(ctx, orphans, nil, false)
@@ -122,21 +119,21 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt
}
func prepareNetworks(project *types.Project) {
for k, network := range project.Networks {
network.Labels = network.Labels.Add(api.NetworkLabel, k)
network.Labels = network.Labels.Add(api.ProjectLabel, project.Name)
network.Labels = network.Labels.Add(api.VersionLabel, api.ComposeVersion)
project.Networks[k] = network
for k, nw := range project.Networks {
nw.Labels = nw.Labels.Add(api.NetworkLabel, k)
nw.Labels = nw.Labels.Add(api.ProjectLabel, project.Name)
nw.Labels = nw.Labels.Add(api.VersionLabel, api.ComposeVersion)
project.Networks[k] = nw
}
}
func (s *composeService) ensureNetworks(ctx context.Context, networks types.Networks) error {
for i, network := range networks {
err := s.ensureNetwork(ctx, &network)
for i, nw := range networks {
err := s.ensureNetwork(ctx, &nw)
if err != nil {
return err
}
networks[i] = network
networks[i] = nw
}
return nil
}
@@ -679,8 +676,8 @@ func getDeployResources(s types.ServiceConfig) container.Resources {
return resources
}
func toUlimits(m map[string]*types.UlimitsConfig) []*units.Ulimit {
var ulimits []*units.Ulimit
func toUlimits(m map[string]*types.UlimitsConfig) []*container.Ulimit {
var ulimits []*container.Ulimit
for name, u := range m {
soft := u.Single
if u.Soft != 0 {
@@ -690,7 +687,7 @@ func toUlimits(m map[string]*types.UlimitsConfig) []*units.Ulimit {
if u.Hard != 0 {
hard = u.Hard
}
ulimits = append(ulimits, &units.Ulimit{
ulimits = append(ulimits, &container.Ulimit{
Name: name,
Hard: int64(hard),
Soft: int64(soft),
@@ -1187,7 +1184,7 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, n *types.Ne
expectedProjectLabel := n.Labels[api.ProjectLabel]
// First, try to find a unique network matching by name or ID
inspect, err := s.apiClient().NetworkInspect(ctx, n.Name, moby.NetworkInspectOptions{})
inspect, err := s.apiClient().NetworkInspect(ctx, n.Name, network.InspectOptions{})
if err == nil {
// NetworkInspect will match on ID prefix, so double check we get the expected one
// as looking for network named `db` we could erroneously matched network ID `db9086999caf`
@@ -1209,7 +1206,7 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, n *types.Ne
// ignore other errors. Typically, an ambiguous request by name results in some generic `invalidParameter` error
// Either not found, or name is ambiguous - use NetworkList to list by name
networks, err := s.apiClient().NetworkList(ctx, moby.NetworkListOptions{
networks, err := s.apiClient().NetworkList(ctx, network.ListOptions{
Filters: filters.NewArgs(filters.Arg("name", n.Name)),
})
if err != nil {
@@ -1217,7 +1214,7 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, n *types.Ne
}
// NetworkList Matches all or part of a network name, so we have to filter for a strict match
networks = utils.Filter(networks, func(net moby.NetworkResource) bool {
networks = utils.Filter(networks, func(net network.Summary) bool {
return net.Name == n.Name
})
@@ -1253,15 +1250,14 @@ func (s *composeService) resolveOrCreateNetwork(ctx context.Context, n *types.Ne
Config: config,
}
}
createOpts := moby.NetworkCreate{
CheckDuplicate: true,
Labels: n.Labels,
Driver: n.Driver,
Options: n.DriverOpts,
Internal: n.Internal,
Attachable: n.Attachable,
IPAM: ipam,
EnableIPv6: n.EnableIPv6,
createOpts := network.CreateOptions{
Labels: n.Labels,
Driver: n.Driver,
Options: n.DriverOpts,
Internal: n.Internal,
Attachable: n.Attachable,
IPAM: ipam,
EnableIPv6: n.EnableIPv6,
}
if n.Ipam.Driver != "" || len(n.Ipam.Config) > 0 {
@@ -1299,7 +1295,7 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne
// filter is used to look for an exact match to prevent e.g. a network
// named `db` from getting erroneously matched to a network with an ID
// like `db9086999caf`
networks, err := s.apiClient().NetworkList(ctx, moby.NetworkListOptions{
networks, err := s.apiClient().NetworkList(ctx, network.ListOptions{
Filters: filters.NewArgs(filters.Arg("name", n.Name)),
})
@@ -1309,16 +1305,15 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne
if len(networks) == 0 {
// in this instance, n.Name is really an ID
sn, err := s.apiClient().NetworkInspect(ctx, n.Name, moby.NetworkInspectOptions{})
if err != nil {
sn, err := s.apiClient().NetworkInspect(ctx, n.Name, network.InspectOptions{})
if err != nil && !errdefs.IsNotFound(err) {
return err
}
networks = append(networks, sn)
}
// NetworkList API doesn't return the exact name match, so we can retrieve more than one network with a request
networks = utils.Filter(networks, func(net moby.NetworkResource) bool {
networks = utils.Filter(networks, func(net network.Inspect) bool {
// later in this function, the name is changed the to ID.
// this function is called during the rebuild stage of `compose watch`.
// we still require just one network back, but we need to run the search on the ID
@@ -1379,7 +1374,7 @@ func (s *composeService) createVolume(ctx context.Context, volume types.VolumeCo
eventName := fmt.Sprintf("Volume %q", volume.Name)
w := progress.ContextWriter(ctx)
w.Event(progress.CreatingEvent(eventName))
_, err := s.apiClient().VolumeCreate(ctx, volume_api.CreateOptions{
_, err := s.apiClient().VolumeCreate(ctx, volumetypes.CreateOptions{
Labels: volume.Labels,
Name: volume.Name,
Driver: volume.Driver,

View File

@@ -31,6 +31,7 @@ import (
containerType "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
imageapi "github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/errdefs"
"golang.org/x/sync/errgroup"
)
@@ -193,7 +194,7 @@ func (s *composeService) ensureNetworksDown(ctx context.Context, project *types.
}
func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName string, projectName string, name string, w progress.Writer) error {
networks, err := s.apiClient().NetworkList(ctx, moby.NetworkListOptions{
networks, err := s.apiClient().NetworkList(ctx, network.ListOptions{
Filters: filters.NewArgs(
projectFilter(projectName),
networkFilter(composeNetworkName)),
@@ -214,7 +215,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s
if net.Name != name {
continue
}
network, err := s.apiClient().NetworkInspect(ctx, net.ID, moby.NetworkInspectOptions{})
nw, err := s.apiClient().NetworkInspect(ctx, net.ID, network.InspectOptions{})
if errdefs.IsNotFound(err) {
w.Event(progress.NewEvent(eventName, progress.Warning, "No resource found to remove"))
return nil
@@ -222,7 +223,7 @@ func (s *composeService) removeNetwork(ctx context.Context, composeNetworkName s
if err != nil {
return err
}
if len(network.Containers) > 0 {
if len(nw.Containers) > 0 {
w.Event(progress.NewEvent(eventName, progress.Warning, "Resource is still in use"))
found++
continue
@@ -326,6 +327,10 @@ func (s *composeService) stopAndRemoveContainer(ctx context.Context, container m
w := progress.ContextWriter(ctx)
eventName := getContainerProgressName(container)
err := s.stopContainer(ctx, w, container, timeout)
if errdefs.IsNotFound(err) {
w.Event(progress.RemovedEvent(eventName))
return nil
}
if err != nil {
return err
}

View File

@@ -29,6 +29,7 @@ import (
containerType "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/volume"
"github.com/docker/docker/errdefs"
"go.uber.org/mock/gomock"
@@ -63,8 +64,8 @@ func TestDown(t *testing.T) {
// network names are not guaranteed to be unique, ensure Compose handles
// cleanup properly if duplicates are inadvertently created
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]moby.NetworkResource{
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]network.Summary{
{ID: "abc123", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}},
{ID: "def456", Name: "myProject_default", Labels: map[string]string{compose.NetworkLabel: "default"}},
}, nil)
@@ -78,16 +79,16 @@ func TestDown(t *testing.T) {
api.EXPECT().ContainerRemove(gomock.Any(), "456", containerType.RemoveOptions{Force: true}).Return(nil)
api.EXPECT().ContainerRemove(gomock.Any(), "789", containerType.RemoveOptions{Force: true}).Return(nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{
Filters: filters.NewArgs(
projectFilter(strings.ToLower(testProject)),
networkFilter("default")),
}).Return([]moby.NetworkResource{
}).Return([]network.Summary{
{ID: "abc123", Name: "myProject_default"},
{ID: "def456", Name: "myProject_default"},
}, nil)
api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(moby.NetworkResource{ID: "abc123"}, nil)
api.EXPECT().NetworkInspect(gomock.Any(), "def456", gomock.Any()).Return(moby.NetworkResource{ID: "def456"}, nil)
api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{ID: "abc123"}, nil)
api.EXPECT().NetworkInspect(gomock.Any(), "def456", gomock.Any()).Return(network.Inspect{ID: "def456"}, nil)
api.EXPECT().NetworkRemove(gomock.Any(), "abc123").Return(nil)
api.EXPECT().NetworkRemove(gomock.Any(), "def456").Return(nil)
@@ -116,8 +117,8 @@ func TestDownRemoveOrphans(t *testing.T) {
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
}).
Return(volume.ListResponse{}, nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]moby.NetworkResource{
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]network.Summary{
{
Name: "myProject_default",
Labels: map[string]string{compose.NetworkLabel: "default"},
@@ -132,13 +133,13 @@ func TestDownRemoveOrphans(t *testing.T) {
api.EXPECT().ContainerRemove(gomock.Any(), "789", containerType.RemoveOptions{Force: true}).Return(nil)
api.EXPECT().ContainerRemove(gomock.Any(), "321", containerType.RemoveOptions{Force: true}).Return(nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{
Filters: filters.NewArgs(
networkFilter("default"),
projectFilter(strings.ToLower(testProject)),
),
}).Return([]moby.NetworkResource{{ID: "abc123", Name: "myProject_default"}}, nil)
api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(moby.NetworkResource{ID: "abc123"}, nil)
}).Return([]network.Summary{{ID: "abc123", Name: "myProject_default"}}, nil)
api.EXPECT().NetworkInspect(gomock.Any(), "abc123", gomock.Any()).Return(network.Inspect{ID: "abc123"}, nil)
api.EXPECT().NetworkRemove(gomock.Any(), "abc123").Return(nil)
err := tested.Down(context.Background(), strings.ToLower(testProject), compose.DownOptions{RemoveOrphans: true})
@@ -164,7 +165,7 @@ func TestDownRemoveVolumes(t *testing.T) {
Return(volume.ListResponse{
Volumes: []*volume.Volume{{Name: "myProject_volume"}},
}, nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return(nil, nil)
api.EXPECT().ContainerStop(gomock.Any(), "123", containerType.StopOptions{}).Return(nil)
@@ -301,7 +302,7 @@ func TestDownRemoveImages_NoLabel(t *testing.T) {
Return(volume.ListResponse{
Volumes: []*volume.Volume{{Name: "myProject_volume"}},
}, nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return(nil, nil)
// ImageList returns no images for the project since they were unlabeled
@@ -329,7 +330,7 @@ func prepareMocks(mockCtrl *gomock.Controller) (*mocks.MockAPIClient, *mocks.Moc
api := mocks.NewMockAPIClient(mockCtrl)
cli := mocks.NewMockCli(mockCtrl)
cli.EXPECT().Client().Return(api).AnyTimes()
cli.EXPECT().Err().Return(os.Stderr).AnyTimes()
cli.EXPECT().Err().Return(streams.NewOut(os.Stderr)).AnyTimes()
cli.EXPECT().Out().Return(streams.NewOut(os.Stdout)).AnyTimes()
return api, cli
}

View File

@@ -21,7 +21,7 @@ import (
"strings"
"time"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
"github.com/docker/compose/v2/pkg/api"
@@ -30,12 +30,12 @@ import (
func (s *composeService) Events(ctx context.Context, projectName string, options api.EventsOptions) error {
projectName = strings.ToLower(projectName)
events, errors := s.apiClient().Events(ctx, moby.EventsOptions{
evts, errors := s.apiClient().Events(ctx, events.ListOptions{
Filters: filters.NewArgs(projectFilter(projectName)),
})
for {
select {
case event := <-events:
case event := <-evts:
// TODO: support other event types
if event.Type != "container" {
continue

View File

@@ -26,6 +26,7 @@ import (
moby "github.com/docker/docker/api/types"
containerType "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/volume"
"go.uber.org/mock/gomock"
"gotest.tools/v3/assert"
@@ -57,8 +58,8 @@ func TestKillAll(t *testing.T) {
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
}).
Return(volume.ListResponse{}, nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]moby.NetworkResource{
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]network.Summary{
{ID: "abc123", Name: "testProject_default"},
}, nil)
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "").Return(nil)
@@ -92,8 +93,8 @@ func TestKillSignal(t *testing.T) {
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
}).
Return(volume.ListResponse{}, nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]moby.NetworkResource{
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]network.Summary{
{ID: "abc123", Name: "testProject_default"},
}, nil)
api.EXPECT().ContainerKill(anyCancellableContext(), "123", "SIGTERM").Return(nil)
@@ -111,6 +112,7 @@ func testContainer(service string, id string, oneOff bool) moby.Container {
ID: id,
Names: []string{name},
Labels: containerLabels(service, oneOff),
State: ContainerExited,
}
}

View File

@@ -25,7 +25,7 @@ import (
"time"
"github.com/compose-spec/compose-go/v2/types"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
)
func (s *composeService) injectSecrets(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
@@ -50,7 +50,7 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje
return err
}
err = s.apiClient().CopyToContainer(ctx, id, "/", &b, moby.CopyToContainerOptions{
err = s.apiClient().CopyToContainer(ctx, id, "/", &b, container.CopyToContainerOptions{
CopyUIDGID: config.UID != "" || config.GID != "",
})
if err != nil {
@@ -84,7 +84,7 @@ func (s *composeService) injectConfigs(ctx context.Context, project *types.Proje
return err
}
err = s.apiClient().CopyToContainer(ctx, id, "/", &b, moby.CopyToContainerOptions{
err = s.apiClient().CopyToContainer(ctx, id, "/", &b, container.CopyToContainerOptions{
CopyUIDGID: config.UID != "" || config.GID != "",
})
if err != nil {

View File

@@ -257,6 +257,11 @@ func (s *composeService) watchContainers(ctx context.Context, //nolint:gocyclo
service := container.Labels[api.ServiceLabel]
switch event.Status {
case "stop":
if inspected.State.Running {
// on sync+restart action the container stops -> dies -> start -> restart
// we do not want to stop the current container, we want to restart it
return nil
}
if _, ok := watched[container.ID]; ok {
eType := api.ContainerEventStopped
if utils.Contains(replaced, container.ID) {
@@ -279,6 +284,11 @@ func (s *composeService) watchContainers(ctx context.Context, //nolint:gocyclo
watched[container.ID] = restarted + 1
// Container terminated.
willRestart := inspected.State.Restarting
if inspected.State.Running {
// on sync+restart action inspected.State.Restarting is false,
// however the container is already running before it restarts
willRestart = true
}
eType := api.ContainerEventExit
if utils.Contains(replaced, container.ID) {

View File

@@ -29,6 +29,7 @@ import (
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/volume"
"go.uber.org/mock/gomock"
"gotest.tools/v3/assert"
@@ -56,8 +57,8 @@ func TestStopTimeout(t *testing.T) {
Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))),
}).
Return(volume.ListResponse{}, nil)
api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]moby.NetworkResource{}, nil)
api.EXPECT().NetworkList(gomock.Any(), network.ListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}).
Return([]network.Summary{}, nil)
timeout := 2 * time.Second
stopConfig := containerType.StopOptions{Timeout: utils.DurationSecondToInt(&timeout)}

View File

@@ -19,6 +19,7 @@ import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"path"
"path/filepath"
@@ -33,6 +34,9 @@ import (
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/watch"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/jonboulle/clockwork"
"github.com/mitchellh/mapstructure"
"github.com/sirupsen/logrus"
@@ -154,6 +158,16 @@ func (s *composeService) watch(ctx context.Context, syncChannel chan bool, proje
if checkIfPathAlreadyBindMounted(trigger.Path, service.Volumes) {
logrus.Warnf("path '%s' also declared by a bind mount volume, this path won't be monitored!\n", trigger.Path)
continue
} else {
var initialSync bool
success, err := trigger.Extensions.Get("x-initialSync", &initialSync)
if err == nil && success && initialSync && (trigger.Action == types.WatchActionSync || trigger.Action == types.WatchActionSyncRestart) {
// Need to check initial files are in container that are meant to be synched from watch action
err := s.initialSync(ctx, project, service, trigger, ignore, syncer)
if err != nil {
return err
}
}
}
paths = append(paths, trigger.Path)
pathLogs = append(pathLogs, fmt.Sprintf("Action %s for path %q", trigger.Action, trigger.Path))
@@ -174,7 +188,11 @@ func (s *composeService) watch(ctx context.Context, syncChannel chan bool, proje
}
watching = true
eg.Go(func() error {
defer watcher.Close() //nolint:errcheck
defer func() {
if err := watcher.Close(); err != nil {
logrus.Debugf("Error closing watcher for service %s: %v", service.Name, err)
}
}()
return s.watchEvents(ctx, project, service.Name, options, watcher, syncer, config.Watch)
})
}
@@ -397,7 +415,7 @@ func (t tarDockerClient) ContainersForService(ctx context.Context, projectName s
}
func (t tarDockerClient) Exec(ctx context.Context, containerID string, cmd []string, in io.Reader) error {
execCfg := moby.ExecConfig{
execCfg := container.ExecOptions{
Cmd: cmd,
AttachStdout: false,
AttachStderr: true,
@@ -409,7 +427,7 @@ func (t tarDockerClient) Exec(ctx context.Context, containerID string, cmd []str
return err
}
startCheck := moby.ExecStartCheck{Tty: false, Detach: false}
startCheck := container.ExecStartOptions{Tty: false, Detach: false}
conn, err := t.s.apiClient().ContainerExecAttach(ctx, execCreateResp.ID, startCheck)
if err != nil {
return err
@@ -457,7 +475,7 @@ func (t tarDockerClient) Exec(ctx context.Context, containerID string, cmd []str
}
func (t tarDockerClient) Untar(ctx context.Context, id string, archive io.ReadCloser) error {
return t.s.apiClient().CopyToContainer(ctx, id, "/", archive, moby.CopyToContainerOptions{
return t.s.apiClient().CopyToContainer(ctx, id, "/", archive, container.CopyToContainerOptions{
CopyUIDGID: true,
})
}
@@ -470,11 +488,17 @@ func (s *composeService) handleWatchBatch(ctx context.Context, project *types.Pr
options.LogTo.Log(api.WatchLogger, fmt.Sprintf("Rebuilding service %q after changes were detected...", serviceName))
// restrict the build to ONLY this service, not any of its dependencies
options.Build.Services = []string{serviceName}
_, err := s.build(ctx, project, *options.Build, nil)
imageNameToIdMap, err := s.build(ctx, project, *options.Build, nil)
if err != nil {
options.LogTo.Log(api.WatchLogger, fmt.Sprintf("Build failed. Error: %v", err))
return err
}
if options.Prune {
s.pruneDanglingImagesOnRebuild(ctx, project.Name, imageNameToIdMap)
}
options.LogTo.Log(api.WatchLogger, fmt.Sprintf("service %q successfully built", serviceName))
err = s.create(ctx, project, api.CreateOptions{
@@ -538,3 +562,146 @@ func writeWatchSyncMessage(log api.LogConsumer, serviceName string, pathMappings
log.Log(api.WatchLogger, fmt.Sprintf("Syncing service %q after %d changes were detected", serviceName, len(pathMappings)))
}
}
func (s *composeService) pruneDanglingImagesOnRebuild(ctx context.Context, projectName string, imageNameToIdMap map[string]string) {
images, err := s.apiClient().ImageList(ctx, image.ListOptions{
Filters: filters.NewArgs(
filters.Arg("dangling", "true"),
filters.Arg("label", api.ProjectLabel+"="+projectName),
),
})
if err != nil {
logrus.Debugf("Failed to list images: %v", err)
return
}
for _, img := range images {
if _, ok := imageNameToIdMap[img.ID]; !ok {
_, err := s.apiClient().ImageRemove(ctx, img.ID, image.RemoveOptions{})
if err != nil {
logrus.Debugf("Failed to remove image %s: %v", img.ID, err)
}
}
}
}
// Walks develop.watch.path and checks which files should be copied inside the container
// ignores develop.watch.ignore, Dockerfile, compose files, bind mounted paths and .git
func (s *composeService) initialSync(ctx context.Context, project *types.Project, service types.ServiceConfig, trigger types.Trigger, ignore watch.PathMatcher, syncer sync.Syncer) error {
dockerFileIgnore, err := watch.NewDockerPatternMatcher("/", []string{"Dockerfile", "*compose*.y*ml"})
if err != nil {
return err
}
triggerIgnore, err := watch.NewDockerPatternMatcher("/", trigger.Ignore)
if err != nil {
return err
}
ignoreInitialSync := watch.NewCompositeMatcher(ignore, dockerFileIgnore, triggerIgnore)
pathsToCopy, err := s.initialSyncFiles(ctx, project, service, trigger, ignoreInitialSync)
if err != nil {
return err
}
return syncer.Sync(ctx, service, pathsToCopy)
}
// Syncs files from develop.watch.path if thy have been modified after the image has been created
//
//nolint:gocyclo
func (s *composeService) initialSyncFiles(ctx context.Context, project *types.Project, service types.ServiceConfig, trigger types.Trigger, ignore watch.PathMatcher) ([]sync.PathMapping, error) {
fi, err := os.Stat(trigger.Path)
if err != nil {
return nil, err
}
timeImageCreated, err := s.imageCreatedTime(ctx, project, service.Name)
if err != nil {
return nil, err
}
var pathsToCopy []sync.PathMapping
switch mode := fi.Mode(); {
case mode.IsDir():
// process directory
err = filepath.WalkDir(trigger.Path, func(path string, d fs.DirEntry, err error) error {
if err != nil {
// handle possible path err, just in case...
return err
}
if trigger.Path == path {
// walk starts at the root directory
return nil
}
if shouldIgnore(filepath.Base(path), ignore) || checkIfPathAlreadyBindMounted(path, service.Volumes) {
// By definition sync ignores bind mounted paths
if d.IsDir() {
// skip folder
return fs.SkipDir
}
return nil // skip file
}
info, err := d.Info()
if err != nil {
return err
}
if !d.IsDir() {
if info.ModTime().Before(timeImageCreated) {
// skip file if it was modified before image creation
return nil
}
rel, err := filepath.Rel(trigger.Path, path)
if err != nil {
return err
}
// only copy files (and not full directories)
pathsToCopy = append(pathsToCopy, sync.PathMapping{
HostPath: path,
ContainerPath: filepath.Join(trigger.Target, rel),
})
}
return nil
})
case mode.IsRegular():
// process file
if fi.ModTime().After(timeImageCreated) && !shouldIgnore(filepath.Base(trigger.Path), ignore) && !checkIfPathAlreadyBindMounted(trigger.Path, service.Volumes) {
pathsToCopy = append(pathsToCopy, sync.PathMapping{
HostPath: trigger.Path,
ContainerPath: trigger.Target,
})
}
}
return pathsToCopy, err
}
func shouldIgnore(name string, ignore watch.PathMatcher) bool {
shouldIgnore, _ := ignore.Matches(name)
// ignore files that match any ignore pattern
return shouldIgnore
}
// gets the image creation time for a service
func (s *composeService) imageCreatedTime(ctx context.Context, project *types.Project, serviceName string) (time.Time, error) {
containers, err := s.apiClient().ContainerList(ctx, container.ListOptions{
All: true,
Filters: filters.NewArgs(
filters.Arg("label", fmt.Sprintf("%s=%s", api.ProjectLabel, project.Name)),
filters.Arg("label", fmt.Sprintf("%s=%s", api.ServiceLabel, serviceName))),
})
if err != nil {
return time.Now(), err
}
if len(containers) == 0 {
return time.Now(), fmt.Errorf("Could not get created time for service's image")
}
img, _, err := s.apiClient().ImageInspectWithRaw(ctx, containers[0].ImageID)
if err != nil {
return time.Now(), err
}
// Need to get oldest one?
timeCreated, err := time.Parse(time.RFC3339Nano, img.Created)
if err != nil {
return time.Now(), err
}
return timeCreated, nil
}

View File

@@ -22,11 +22,14 @@ import (
"time"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/streams"
"github.com/docker/compose/v2/internal/sync"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/mocks"
"github.com/docker/compose/v2/pkg/watch"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/image"
"github.com/jonboulle/clockwork"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
@@ -113,18 +116,32 @@ func (s stdLogger) Register(container string) {
func TestWatch_Sync(t *testing.T) {
mockCtrl := gomock.NewController(t)
cli := mocks.NewMockCli(mockCtrl)
cli.EXPECT().Err().Return(os.Stderr).AnyTimes()
cli.EXPECT().Err().Return(streams.NewOut(os.Stderr)).AnyTimes()
cli.EXPECT().BuildKitEnabled().Return(true, nil)
apiClient := mocks.NewMockAPIClient(mockCtrl)
apiClient.EXPECT().ContainerList(gomock.Any(), gomock.Any()).Return([]moby.Container{
testContainer("test", "123", false),
}, nil).AnyTimes()
// we expect the image to be pruned
apiClient.EXPECT().ImageList(gomock.Any(), image.ListOptions{
Filters: filters.NewArgs(
filters.Arg("dangling", "true"),
filters.Arg("label", api.ProjectLabel+"=myProjectName"),
),
}).Return([]image.Summary{
{ID: "123"},
{ID: "456"},
}, nil).Times(1)
apiClient.EXPECT().ImageRemove(gomock.Any(), "123", image.RemoveOptions{}).Times(1)
apiClient.EXPECT().ImageRemove(gomock.Any(), "456", image.RemoveOptions{}).Times(1)
//
cli.EXPECT().Client().Return(apiClient).AnyTimes()
ctx, cancelFunc := context.WithCancel(context.Background())
t.Cleanup(cancelFunc)
proj := types.Project{
Name: "myProjectName",
Services: types.Services{
"test": {
Name: "test",
@@ -147,6 +164,7 @@ func TestWatch_Sync(t *testing.T) {
err := service.watchEvents(ctx, &proj, "test", api.WatchOptions{
Build: &api.BuildOptions{},
LogTo: stdLogger{},
Prune: true,
}, watcher, syncer, []types.Trigger{
{
Path: "/sync",

View File

@@ -331,13 +331,13 @@ func TestBuildPlatformsWithCorrectBuildxConfig(t *testing.T) {
})
t.Run("multi-arch up --build", func(t *testing.T) {
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms", "up", "--build")
res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms", "up", "--build", "--menu=false")
assert.NilError(t, res.Error, res.Stderr())
res.Assert(t, icmd.Expected{Out: "platforms-1 exited with code 0"})
})
t.Run("use DOCKER_DEFAULT_PLATFORM value when up --build", func(t *testing.T) {
cmd := c.NewDockerComposeCmd(t, "--project-directory", "fixtures/build-test/platforms", "up", "--build")
cmd := c.NewDockerComposeCmd(t, "--project-directory", "fixtures/build-test/platforms", "up", "--build", "--menu=false")
res := icmd.RunCmd(cmd, func(cmd *icmd.Cmd) {
cmd.Env = append(cmd.Env, "DOCKER_DEFAULT_PLATFORM=linux/amd64")
})

View File

@@ -222,3 +222,24 @@ func TestCommentsInEnvFile(t *testing.T) {
c.RunDockerComposeCmd(t, "--project-name", "env-file-comments", "down", "--rmi", "all")
})
}
func TestUnsetEnv(t *testing.T) {
c := NewParallelCLI(t)
t.Cleanup(func() {
c.RunDockerComposeCmd(t, "--project-name", "empty-variable", "down", "--rmi", "all")
})
t.Run("override env variable", func(t *testing.T) {
c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/empty-variable/compose.yaml", "build")
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/empty-variable/compose.yaml",
"run", "-e", "EMPTY=hello", "--rm", "empty-variable")
res.Assert(t, icmd.Expected{Out: `=hello=`})
})
t.Run("unset env variable", func(t *testing.T) {
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/environment/empty-variable/compose.yaml",
"run", "--rm", "empty-variable")
res.Assert(t, icmd.Expected{Out: `==`})
})
}

View File

@@ -37,7 +37,7 @@ func TestLocalComposeRun(t *testing.T) {
"Hello one more time")
lines = Lines(res.Stdout())
assert.Equal(t, lines[len(lines)-1], "Hello one more time", res.Stdout())
assert.Assert(t, !strings.Contains(res.Combined(), "orphan"))
assert.Assert(t, strings.Contains(res.Combined(), "orphan"))
})
t.Run("check run container exited", func(t *testing.T) {
@@ -135,7 +135,7 @@ func TestLocalComposeRun(t *testing.T) {
t.Run("run starts only container and dependencies", func(t *testing.T) {
// ensure that even if another service is up run does not start it: https://github.com/docker/compose/issues/9459
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/deps.yaml", "up", "service_b")
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/deps.yaml", "up", "service_b", "--menu=false")
res.Assert(t, icmd.Success)
res = c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/deps.yaml", "run", "service_a")

View File

@@ -165,7 +165,7 @@ func TestAttachRestart(t *testing.T) {
func TestInitContainer(t *testing.T) {
c := NewParallelCLI(t)
res := c.RunDockerComposeCmd(t, "--ansi=never", "--project-directory", "./fixtures/init-container", "up")
res := c.RunDockerComposeCmd(t, "--ansi=never", "--project-directory", "./fixtures/init-container", "up", "--menu=false")
defer c.RunDockerComposeCmd(t, "-p", "init-container", "down")
testify.Regexp(t, "foo-1 | hello(?m:.*)bar-1 | world", res.Stdout())
}
@@ -293,7 +293,7 @@ func TestStopWithDependenciesAttached(t *testing.T) {
cleanup()
t.Cleanup(cleanup)
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "-p", projectName, "up", "--attach-dependencies", "foo")
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "-p", projectName, "up", "--attach-dependencies", "foo", "--menu=false")
res.Assert(t, icmd.Expected{Out: "exited with code 0"})
}
@@ -388,3 +388,20 @@ func TestNestedDotEnv(t *testing.T) {
})
}
func TestUnnecesaryResources(t *testing.T) {
const projectName = "compose-e2e-unnecessary-resources"
c := NewParallelCLI(t)
t.Cleanup(func() {
c.RunDockerComposeCmd(t, "-p", projectName, "down", "-t=0")
})
res := c.RunDockerComposeCmdNoCheck(t, "-f", "./fixtures/external/compose.yaml", "-p", projectName, "up", "-d")
res.Assert(t, icmd.Expected{
ExitCode: 1,
Err: "network foo_bar declared as external, but could not be found",
})
c.RunDockerComposeCmd(t, "-f", "./fixtures/external/compose.yaml", "-p", projectName, "up", "-d", "test")
// Should not fail as missing external network is not used
}

View File

@@ -51,7 +51,7 @@ func TestUpExitCodeFrom(t *testing.T) {
c := NewParallelCLI(t)
const projectName = "e2e-exit-code-from"
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/start-fail/start-depends_on-long-lived.yaml", "--project-name", projectName, "up", "--exit-code-from=failure", "failure")
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/start-fail/start-depends_on-long-lived.yaml", "--project-name", projectName, "up", "--menu=false", "--exit-code-from=failure", "failure")
res.Assert(t, icmd.Expected{ExitCode: 42})
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--remove-orphans")
@@ -61,7 +61,7 @@ func TestUpExitCodeFromContainerKilled(t *testing.T) {
c := NewParallelCLI(t)
const projectName = "e2e-exit-code-from-kill"
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/start-fail/start-depends_on-long-lived.yaml", "--project-name", projectName, "up", "--exit-code-from=test")
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/start-fail/start-depends_on-long-lived.yaml", "--project-name", projectName, "up", "--menu=false", "--exit-code-from=test")
res.Assert(t, icmd.Expected{ExitCode: 143})
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--remove-orphans")
@@ -85,7 +85,7 @@ func TestStdoutStderr(t *testing.T) {
c := NewParallelCLI(t)
const projectName = "e2e-stdout-stderr"
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/stdout-stderr/compose.yaml", "--project-name", projectName, "up")
res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/stdout-stderr/compose.yaml", "--project-name", projectName, "up", "--menu=false")
res.Assert(t, icmd.Expected{Out: "log to stdout", Err: "log to stderr"})
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--remove-orphans")

View File

@@ -0,0 +1,17 @@
# 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.
FROM alpine
ENV EMPTY=not_empty
CMD ["sh", "-c", "echo \"=$EMPTY=\""]

View File

@@ -0,0 +1,7 @@
services:
empty-variable:
build:
context: .
image: empty-variable
environment:
- EMPTY # expect to propagate value from user's env OR unset in container

14
pkg/e2e/fixtures/external/compose.yaml vendored Normal file
View File

@@ -0,0 +1,14 @@
services:
test:
image: nginx:alpine
other:
image: nginx:alpine
networks:
test_network:
ipv4_address: 8.8.8.8
networks:
test_network:
external: true
name: foo_bar

View File

@@ -0,0 +1 @@
COMPOSE_REMOVE_ORPHANS=true

View File

@@ -0,0 +1,7 @@
services:
orphan:
profiles: [run]
image: alpine
command: echo hello
test:
image: nginx:alpine

View File

@@ -116,7 +116,7 @@ func TestLocalComposeLargeLogs(t *testing.T) {
}
assert.NilError(t, f.Close())
cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/logs-test/cat.yaml", "--project-name", projectName, "up", "--abort-on-container-exit")
cmd := c.NewDockerComposeCmd(t, "-f", "./fixtures/logs-test/cat.yaml", "--project-name", projectName, "up", "--abort-on-container-exit", "--menu=false")
cmd.Stdout = io.Discard
res := icmd.RunCmd(cmd)
res.Assert(t, icmd.Expected{Out: "test-1 exited with code 0"})

View File

@@ -37,9 +37,9 @@ func TestComposeMetrics(t *testing.T) {
res.Assert(t, icmd.Expected{ExitCode: 15, Err: "services.simple Additional property wrongField is not allowed"})
res = c.RunDockerComposeCmdNoCheck(t, "up")
res.Assert(t, icmd.Expected{ExitCode: 14, Err: "no configuration file provided: not found"})
res = c.RunDockerComposeCmdNoCheck(t, "up", "-f", "fixtures/wrong-composefile/compose.yaml")
res = c.RunDockerComposeCmdNoCheck(t, "up", "-f", "fixtures/wrong-composefile/compose.yaml", "--menu=false")
res.Assert(t, icmd.Expected{ExitCode: 16, Err: "unknown shorthand flag: 'f' in -f"})
res = c.RunDockerComposeCmdNoCheck(t, "up", "--file", "fixtures/wrong-composefile/compose.yaml")
res = c.RunDockerComposeCmdNoCheck(t, "up", "--file", "fixtures/wrong-composefile/compose.yaml", "--menu=false")
res.Assert(t, icmd.Expected{ExitCode: 16, Err: "unknown flag: --file"})
res = c.RunDockerComposeCmdNoCheck(t, "donw", "--file", "fixtures/wrong-composefile/compose.yaml")
res.Assert(t, icmd.Expected{ExitCode: 16, Err: `unknown docker command: "compose donw"`})

39
pkg/e2e/orphans_test.go Normal file
View File

@@ -0,0 +1,39 @@
/*
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 e2e
import (
"strings"
"testing"
"gotest.tools/v3/assert"
)
func TestRemoveOrphans(t *testing.T) {
c := NewCLI(t)
const projectName = "compose-e2e-orphans"
c.RunDockerComposeCmd(t, "-f", "./fixtures/orphans/compose.yaml", "-p", projectName, "run", "orphan")
res := c.RunDockerComposeCmd(t, "-p", projectName, "ps", "--all")
assert.Check(t, strings.Contains(res.Combined(), "compose-e2e-orphans-orphan-run-"))
c.RunDockerComposeCmd(t, "-f", "./fixtures/orphans/compose.yaml", "-p", projectName, "up", "-d")
res = c.RunDockerComposeCmd(t, "-p", projectName, "ps", "--all")
assert.Check(t, !strings.Contains(res.Combined(), "compose-e2e-orphans-orphan-run-"))
}

View File

@@ -104,7 +104,7 @@ func TestPauseServiceAlreadyPaused(t *testing.T) {
t.Cleanup(cleanup)
// launch a and wait for it to come up
cli.RunDockerComposeCmd(t, "up", "--wait", "a")
cli.RunDockerComposeCmd(t, "up", "--menu=false", "--wait", "a")
HTTPGetWithRetry(t, urlForService(t, cli, "a", 80), http.StatusOK, 50*time.Millisecond, 10*time.Second)
// pause a twice - first time should pass, second time fail

View File

@@ -71,6 +71,7 @@ func TestUpDependenciesNotStopped(t *testing.T) {
testCmd := c.NewDockerComposeCmd(t,
"-f=./fixtures/ups-deps-stop/compose.yaml",
"up",
"--menu=false",
"app",
)

View File

@@ -34,7 +34,6 @@ import (
)
func TestWatch(t *testing.T) {
t.Skip("Skipping watch tests until we can figure out why they are flaky/failing")
services := []string{"alpine", "busybox", "debian"}
for _, svcName := range services {

View File

@@ -289,7 +289,7 @@ func (mr *MockAPIClientMockRecorder) ContainerDiff(arg0, arg1 any) *gomock.Call
}
// ContainerExecAttach mocks base method.
func (m *MockAPIClient) ContainerExecAttach(arg0 context.Context, arg1 string, arg2 types.ExecStartCheck) (types.HijackedResponse, error) {
func (m *MockAPIClient) ContainerExecAttach(arg0 context.Context, arg1 string, arg2 container.ExecStartOptions) (types.HijackedResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ContainerExecAttach", arg0, arg1, arg2)
ret0, _ := ret[0].(types.HijackedResponse)
@@ -304,7 +304,7 @@ func (mr *MockAPIClientMockRecorder) ContainerExecAttach(arg0, arg1, arg2 any) *
}
// ContainerExecCreate mocks base method.
func (m *MockAPIClient) ContainerExecCreate(arg0 context.Context, arg1 string, arg2 types.ExecConfig) (types.IDResponse, error) {
func (m *MockAPIClient) ContainerExecCreate(arg0 context.Context, arg1 string, arg2 container.ExecOptions) (types.IDResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ContainerExecCreate", arg0, arg1, arg2)
ret0, _ := ret[0].(types.IDResponse)
@@ -319,10 +319,10 @@ func (mr *MockAPIClientMockRecorder) ContainerExecCreate(arg0, arg1, arg2 any) *
}
// ContainerExecInspect mocks base method.
func (m *MockAPIClient) ContainerExecInspect(arg0 context.Context, arg1 string) (types.ContainerExecInspect, error) {
func (m *MockAPIClient) ContainerExecInspect(arg0 context.Context, arg1 string) (container.ExecInspect, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ContainerExecInspect", arg0, arg1)
ret0, _ := ret[0].(types.ContainerExecInspect)
ret0, _ := ret[0].(container.ExecInspect)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -348,7 +348,7 @@ func (mr *MockAPIClientMockRecorder) ContainerExecResize(arg0, arg1, arg2 any) *
}
// ContainerExecStart mocks base method.
func (m *MockAPIClient) ContainerExecStart(arg0 context.Context, arg1 string, arg2 types.ExecStartCheck) error {
func (m *MockAPIClient) ContainerExecStart(arg0 context.Context, arg1 string, arg2 container.ExecStartOptions) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ContainerExecStart", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
@@ -536,10 +536,10 @@ func (mr *MockAPIClientMockRecorder) ContainerStart(arg0, arg1, arg2 any) *gomoc
}
// ContainerStatPath mocks base method.
func (m *MockAPIClient) ContainerStatPath(arg0 context.Context, arg1, arg2 string) (types.ContainerPathStat, error) {
func (m *MockAPIClient) ContainerStatPath(arg0 context.Context, arg1, arg2 string) (container.PathStat, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ContainerStatPath", arg0, arg1, arg2)
ret0, _ := ret[0].(types.ContainerPathStat)
ret0, _ := ret[0].(container.PathStat)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -551,10 +551,10 @@ func (mr *MockAPIClientMockRecorder) ContainerStatPath(arg0, arg1, arg2 any) *go
}
// ContainerStats mocks base method.
func (m *MockAPIClient) ContainerStats(arg0 context.Context, arg1 string, arg2 bool) (types.ContainerStats, error) {
func (m *MockAPIClient) ContainerStats(arg0 context.Context, arg1 string, arg2 bool) (container.StatsResponseReader, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ContainerStats", arg0, arg1, arg2)
ret0, _ := ret[0].(types.ContainerStats)
ret0, _ := ret[0].(container.StatsResponseReader)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -566,10 +566,10 @@ func (mr *MockAPIClientMockRecorder) ContainerStats(arg0, arg1, arg2 any) *gomoc
}
// ContainerStatsOneShot mocks base method.
func (m *MockAPIClient) ContainerStatsOneShot(arg0 context.Context, arg1 string) (types.ContainerStats, error) {
func (m *MockAPIClient) ContainerStatsOneShot(arg0 context.Context, arg1 string) (container.StatsResponseReader, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ContainerStatsOneShot", arg0, arg1)
ret0, _ := ret[0].(types.ContainerStats)
ret0, _ := ret[0].(container.StatsResponseReader)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -654,10 +654,10 @@ func (mr *MockAPIClientMockRecorder) ContainerWait(arg0, arg1, arg2 any) *gomock
}
// ContainersPrune mocks base method.
func (m *MockAPIClient) ContainersPrune(arg0 context.Context, arg1 filters.Args) (types.ContainersPruneReport, error) {
func (m *MockAPIClient) ContainersPrune(arg0 context.Context, arg1 filters.Args) (container.PruneReport, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ContainersPrune", arg0, arg1)
ret0, _ := ret[0].(types.ContainersPruneReport)
ret0, _ := ret[0].(container.PruneReport)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -669,11 +669,11 @@ func (mr *MockAPIClientMockRecorder) ContainersPrune(arg0, arg1 any) *gomock.Cal
}
// CopyFromContainer mocks base method.
func (m *MockAPIClient) CopyFromContainer(arg0 context.Context, arg1, arg2 string) (io.ReadCloser, types.ContainerPathStat, error) {
func (m *MockAPIClient) CopyFromContainer(arg0 context.Context, arg1, arg2 string) (io.ReadCloser, container.PathStat, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CopyFromContainer", arg0, arg1, arg2)
ret0, _ := ret[0].(io.ReadCloser)
ret1, _ := ret[1].(types.ContainerPathStat)
ret1, _ := ret[1].(container.PathStat)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
}
@@ -685,7 +685,7 @@ func (mr *MockAPIClientMockRecorder) CopyFromContainer(arg0, arg1, arg2 any) *go
}
// CopyToContainer mocks base method.
func (m *MockAPIClient) CopyToContainer(arg0 context.Context, arg1, arg2 string, arg3 io.Reader, arg4 types.CopyToContainerOptions) error {
func (m *MockAPIClient) CopyToContainer(arg0 context.Context, arg1, arg2 string, arg3 io.Reader, arg4 container.CopyToContainerOptions) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "CopyToContainer", arg0, arg1, arg2, arg3, arg4)
ret0, _ := ret[0].(error)
@@ -772,7 +772,7 @@ func (mr *MockAPIClientMockRecorder) DistributionInspect(arg0, arg1, arg2 any) *
}
// Events mocks base method.
func (m *MockAPIClient) Events(arg0 context.Context, arg1 types.EventsOptions) (<-chan events.Message, <-chan error) {
func (m *MockAPIClient) Events(arg0 context.Context, arg1 events.ListOptions) (<-chan events.Message, <-chan error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Events", arg0, arg1)
ret0, _ := ret[0].(<-chan events.Message)
@@ -846,7 +846,7 @@ func (mr *MockAPIClientMockRecorder) ImageHistory(arg0, arg1 any) *gomock.Call {
}
// ImageImport mocks base method.
func (m *MockAPIClient) ImageImport(arg0 context.Context, arg1 types.ImageImportSource, arg2 string, arg3 image.ImportOptions) (io.ReadCloser, error) {
func (m *MockAPIClient) ImageImport(arg0 context.Context, arg1 image.ImportSource, arg2 string, arg3 image.ImportOptions) (io.ReadCloser, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ImageImport", arg0, arg1, arg2, arg3)
ret0, _ := ret[0].(io.ReadCloser)
@@ -892,10 +892,10 @@ func (mr *MockAPIClientMockRecorder) ImageList(arg0, arg1 any) *gomock.Call {
}
// ImageLoad mocks base method.
func (m *MockAPIClient) ImageLoad(arg0 context.Context, arg1 io.Reader, arg2 bool) (types.ImageLoadResponse, error) {
func (m *MockAPIClient) ImageLoad(arg0 context.Context, arg1 io.Reader, arg2 bool) (image.LoadResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ImageLoad", arg0, arg1, arg2)
ret0, _ := ret[0].(types.ImageLoadResponse)
ret0, _ := ret[0].(image.LoadResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -967,7 +967,7 @@ func (mr *MockAPIClientMockRecorder) ImageSave(arg0, arg1 any) *gomock.Call {
}
// ImageSearch mocks base method.
func (m *MockAPIClient) ImageSearch(arg0 context.Context, arg1 string, arg2 types.ImageSearchOptions) ([]registry.SearchResult, error) {
func (m *MockAPIClient) ImageSearch(arg0 context.Context, arg1 string, arg2 registry.SearchOptions) ([]registry.SearchResult, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ImageSearch", arg0, arg1, arg2)
ret0, _ := ret[0].([]registry.SearchResult)
@@ -996,10 +996,10 @@ func (mr *MockAPIClientMockRecorder) ImageTag(arg0, arg1, arg2 any) *gomock.Call
}
// ImagesPrune mocks base method.
func (m *MockAPIClient) ImagesPrune(arg0 context.Context, arg1 filters.Args) (types.ImagesPruneReport, error) {
func (m *MockAPIClient) ImagesPrune(arg0 context.Context, arg1 filters.Args) (image.PruneReport, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ImagesPrune", arg0, arg1)
ret0, _ := ret[0].(types.ImagesPruneReport)
ret0, _ := ret[0].(image.PruneReport)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -1064,10 +1064,10 @@ func (mr *MockAPIClientMockRecorder) NetworkConnect(arg0, arg1, arg2, arg3 any)
}
// NetworkCreate mocks base method.
func (m *MockAPIClient) NetworkCreate(arg0 context.Context, arg1 string, arg2 types.NetworkCreate) (types.NetworkCreateResponse, error) {
func (m *MockAPIClient) NetworkCreate(arg0 context.Context, arg1 string, arg2 network.CreateOptions) (network.CreateResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetworkCreate", arg0, arg1, arg2)
ret0, _ := ret[0].(types.NetworkCreateResponse)
ret0, _ := ret[0].(network.CreateResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -1093,10 +1093,10 @@ func (mr *MockAPIClientMockRecorder) NetworkDisconnect(arg0, arg1, arg2, arg3 an
}
// NetworkInspect mocks base method.
func (m *MockAPIClient) NetworkInspect(arg0 context.Context, arg1 string, arg2 types.NetworkInspectOptions) (types.NetworkResource, error) {
func (m *MockAPIClient) NetworkInspect(arg0 context.Context, arg1 string, arg2 network.InspectOptions) (network.Inspect, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetworkInspect", arg0, arg1, arg2)
ret0, _ := ret[0].(types.NetworkResource)
ret0, _ := ret[0].(network.Inspect)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -1108,10 +1108,10 @@ func (mr *MockAPIClientMockRecorder) NetworkInspect(arg0, arg1, arg2 any) *gomoc
}
// NetworkInspectWithRaw mocks base method.
func (m *MockAPIClient) NetworkInspectWithRaw(arg0 context.Context, arg1 string, arg2 types.NetworkInspectOptions) (types.NetworkResource, []byte, error) {
func (m *MockAPIClient) NetworkInspectWithRaw(arg0 context.Context, arg1 string, arg2 network.InspectOptions) (network.Inspect, []byte, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetworkInspectWithRaw", arg0, arg1, arg2)
ret0, _ := ret[0].(types.NetworkResource)
ret0, _ := ret[0].(network.Inspect)
ret1, _ := ret[1].([]byte)
ret2, _ := ret[2].(error)
return ret0, ret1, ret2
@@ -1124,10 +1124,10 @@ func (mr *MockAPIClientMockRecorder) NetworkInspectWithRaw(arg0, arg1, arg2 any)
}
// NetworkList mocks base method.
func (m *MockAPIClient) NetworkList(arg0 context.Context, arg1 types.NetworkListOptions) ([]types.NetworkResource, error) {
func (m *MockAPIClient) NetworkList(arg0 context.Context, arg1 network.ListOptions) ([]network.Inspect, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetworkList", arg0, arg1)
ret0, _ := ret[0].([]types.NetworkResource)
ret0, _ := ret[0].([]network.Inspect)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -1153,10 +1153,10 @@ func (mr *MockAPIClientMockRecorder) NetworkRemove(arg0, arg1 any) *gomock.Call
}
// NetworksPrune mocks base method.
func (m *MockAPIClient) NetworksPrune(arg0 context.Context, arg1 filters.Args) (types.NetworksPruneReport, error) {
func (m *MockAPIClient) NetworksPrune(arg0 context.Context, arg1 filters.Args) (network.PruneReport, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "NetworksPrune", arg0, arg1)
ret0, _ := ret[0].(types.NetworksPruneReport)
ret0, _ := ret[0].(network.PruneReport)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -1818,10 +1818,10 @@ func (mr *MockAPIClientMockRecorder) VolumeUpdate(arg0, arg1, arg2, arg3 any) *g
}
// VolumesPrune mocks base method.
func (m *MockAPIClient) VolumesPrune(arg0 context.Context, arg1 filters.Args) (types.VolumesPruneReport, error) {
func (m *MockAPIClient) VolumesPrune(arg0 context.Context, arg1 filters.Args) (volume.PruneReport, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "VolumesPrune", arg0, arg1)
ret0, _ := ret[0].(types.VolumesPruneReport)
ret0, _ := ret[0].(volume.PruneReport)
ret1, _ := ret[1].(error)
return ret0, ret1
}

View File

@@ -10,7 +10,6 @@
package mocks
import (
io "io"
reflect "reflect"
command "github.com/docker/cli/cli/command"
@@ -198,10 +197,10 @@ func (mr *MockCliMockRecorder) DockerEndpoint() *gomock.Call {
}
// Err mocks base method.
func (m *MockCli) Err() io.Writer {
func (m *MockCli) Err() *streams.Out {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Err")
ret0, _ := ret[0].(io.Writer)
ret0, _ := ret[0].(*streams.Out)
return ret0
}

96
pkg/progress/json.go Normal file
View File

@@ -0,0 +1,96 @@
/*
Copyright 2024 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
import (
"context"
"encoding/json"
"fmt"
"io"
)
type jsonWriter struct {
out io.Writer
done chan bool
dryRun bool
}
type jsonMessage struct {
DryRun bool `json:"dry-run,omitempty"`
Tail bool `json:"tail,omitempty"`
ID string `json:"id,omitempty"`
ParentID string `json:"parent_id,omitempty"`
Text string `json:"text,omitempty"`
Status string `json:"status,omitempty"`
Current int64 `json:"current,omitempty"`
Total int64 `json:"total,omitempty"`
Percent int `json:"percent,omitempty"`
}
func (p *jsonWriter) Start(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
case <-p.done:
return nil
}
}
func (p *jsonWriter) Event(e Event) {
var message = &jsonMessage{
DryRun: p.dryRun,
Tail: false,
ID: e.ID,
Text: e.Text,
Status: e.StatusText,
ParentID: e.ParentID,
Current: e.Current,
Total: e.Total,
Percent: e.Percent,
}
marshal, err := json.Marshal(message)
if err == nil {
fmt.Fprintln(p.out, string(marshal))
}
}
func (p *jsonWriter) Events(events []Event) {
for _, e := range events {
p.Event(e)
}
}
func (p *jsonWriter) TailMsgf(msg string, args ...interface{}) {
var message = &jsonMessage{
DryRun: p.dryRun,
Tail: true,
ID: "",
Text: fmt.Sprintf(msg, args...),
Status: "",
}
marshal, err := json.Marshal(message)
if err == nil {
fmt.Fprintln(p.out, string(marshal))
}
}
func (p *jsonWriter) Stop() {
p.done <- true
}
func (p *jsonWriter) HasMore(bool) {
}

View File

@@ -21,9 +21,7 @@ import (
"io"
"sync"
"github.com/containerd/console"
"github.com/moby/term"
"github.com/sirupsen/logrus"
"github.com/docker/cli/cli/streams"
"golang.org/x/sync/errgroup"
"github.com/docker/compose/v2/pkg/api"
@@ -59,14 +57,14 @@ type progressFunc func(context.Context) error
type progressFuncWithStatus func(context.Context) (string, error)
// Run will run a writer and the progress function in parallel
func Run(ctx context.Context, pf progressFunc, out io.Writer) error {
func Run(ctx context.Context, pf progressFunc, out *streams.Out) error {
_, err := RunWithStatus(ctx, func(ctx context.Context) (string, error) {
return "", pf(ctx)
}, out, "Running")
return err
}
func RunWithTitle(ctx context.Context, pf progressFunc, out io.Writer, progressTitle string) error {
func RunWithTitle(ctx context.Context, pf progressFunc, out *streams.Out, progressTitle string) error {
_, err := RunWithStatus(ctx, func(ctx context.Context) (string, error) {
return "", pf(ctx)
}, out, progressTitle)
@@ -74,7 +72,7 @@ func RunWithTitle(ctx context.Context, pf progressFunc, out io.Writer, progressT
}
// RunWithStatus will run a writer and the progress function in parallel and return a status
func RunWithStatus(ctx context.Context, pf progressFuncWithStatus, out io.Writer, progressTitle string) (string, error) {
func RunWithStatus(ctx context.Context, pf progressFuncWithStatus, out *streams.Out, progressTitle string) (string, error) {
eg, _ := errgroup.WithContext(ctx)
w, err := NewWriter(ctx, out, progressTitle)
var result string
@@ -109,14 +107,16 @@ const (
ModePlain = "plain"
// ModeQuiet don't display events
ModeQuiet = "quiet"
// ModeJSON outputs a machine-readable JSON stream
ModeJSON = "json"
)
// Mode define how progress should be rendered, either as ModePlain or ModeTTY
var Mode = ModeAuto
// NewWriter returns a new multi-progress writer
func NewWriter(ctx context.Context, out io.Writer, progressTitle string) (Writer, error) {
_, isTerminal := term.GetFdInfo(out)
func NewWriter(ctx context.Context, out *streams.Out, progressTitle string) (Writer, error) {
isTerminal := out.IsTerminal()
dryRun, ok := ctx.Value(api.DryRunKey{}).(bool)
if !ok {
dryRun = false
@@ -124,16 +124,20 @@ func NewWriter(ctx context.Context, out io.Writer, progressTitle string) (Writer
if Mode == ModeQuiet {
return quiet{}, nil
}
f, isConsole := out.(console.File) // see https://github.com/docker/compose/issues/10560
if Mode == ModeAuto && isTerminal && isConsole {
return newTTYWriter(f, dryRun, progressTitle)
tty := Mode == ModeTTY
if Mode == ModeAuto && isTerminal {
tty = true
}
if Mode == ModeTTY {
if !isConsole {
logrus.Warn("Terminal is not a POSIX console")
} else {
return newTTYWriter(f, dryRun, progressTitle)
}
if tty {
return newTTYWriter(out, dryRun, progressTitle)
}
if Mode == ModeJSON {
return &jsonWriter{
out: out,
done: make(chan bool),
dryRun: dryRun,
}, nil
}
return &plainWriter{
out: out,
@@ -142,14 +146,9 @@ func NewWriter(ctx context.Context, out io.Writer, progressTitle string) (Writer
}, nil
}
func newTTYWriter(out console.File, dryRun bool, progressTitle string) (Writer, error) {
con, err := console.ConsoleFromFile(out)
if err != nil {
return nil, err
}
func newTTYWriter(out io.Writer, dryRun bool, progressTitle string) (Writer, error) {
return &ttyWriter{
out: con,
out: out,
eventIDs: []string{},
events: map[string]Event{},
repeated: false,