Compare commits

..

28 Commits

Author SHA1 Message Date
Guillaume Lours
e28b223650 Merge pull request #10793 from milas/dockerfile-cache-mounts
ci: speed up a couple Dockerfile targets w/ cache mount
2023-07-10 19:26:41 +02:00
Milas Bowman
1964693074 ci: speed up a couple Dockerfile targets w/ cache mount
The local Go package module path was missing from a couple of jobs,
which made them slower than needed since they were re-downloading
a bunch of dependencies.

In particular, this makes `make lint` waaaay faster!

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-07-10 13:13:10 -04:00
Guillaume Lours
dc74e6aa0e Merge pull request #10776 from docker/dependabot/go_modules/github.com/docker/buildx-0.11.1
build(deps): bump github.com/docker/buildx from 0.11.0 to 0.11.1
2023-07-10 18:15:39 +02:00
dependabot[bot]
b182cf6850 build(deps): bump github.com/docker/buildx from 0.11.0 to 0.11.1
Bumps [github.com/docker/buildx](https://github.com/docker/buildx) from 0.11.0 to 0.11.1.
- [Release notes](https://github.com/docker/buildx/releases)
- [Commits](https://github.com/docker/buildx/compare/v0.11.0...v0.11.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>
2023-07-10 15:51:31 +00:00
Guillaume Lours
f330b24632 Merge pull request #10788 from docker/dependabot/go_modules/github.com/docker/docker-24.0.4incompatible
build(deps): bump github.com/docker/docker from 24.0.2+incompatible to 24.0.4+incompatible
2023-07-10 17:49:45 +02:00
Guillaume Lours
8339269e13 Merge pull request #10789 from ndeloof/run_no_deps
Apply no-deps before we select and mutate target service
2023-07-10 15:46:01 +02:00
Guillaume Lours
ee6aeed84e Merge pull request #10700 from ndeloof/attach
support `attach`
2023-07-10 15:17:44 +02:00
Guillaume Lours
7a9dfa4284 Merge pull request #10790 from milas/e2e-process-leak
test: fix process leak in wait e2e test
2023-07-10 15:09:41 +02:00
Guillaume Lours
29daae3d6e Merge pull request #10784 from shantanoo-desai/v2
fix(secrets): file permission value does not comply with spec
2023-07-10 14:54:16 +02:00
Milas Bowman
8dea7b5cae test: fix process leak in wait e2e test
* Run `down` before and after test to not leave around containers
* Kill the `wait` process that's waiting on `infinity`
  * NOTE: If the test is actually working, this should exit once
    the `down` happens, but this ensures that we kill everything
    we start

I'd like to generalize more of this into the framework, but this
is a quick fix to prevent filling up CI machines with tons of
processes over time.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-07-10 08:42:09 -04:00
Guillaume Lours
bc6ad2e4a4 Merge pull request #10764 from docker/dependabot/go_modules/github.com/opencontainers/image-spec-1.1.0-rc4
build(deps): bump github.com/opencontainers/image-spec from 1.1.0-rc3 to 1.1.0-rc4
2023-07-10 14:39:44 +02:00
Nicolas De Loof
e6a7694b8d Apply no-deps before we select and mutate target service
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-07-10 14:37:42 +02:00
Nicolas De Loof
46d936c750 support attach
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-07-10 14:34:28 +02:00
dependabot[bot]
15bc7850bb build(deps): bump github.com/opencontainers/image-spec
Bumps [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) from 1.1.0-rc3 to 1.1.0-rc4.
- [Release notes](https://github.com/opencontainers/image-spec/releases)
- [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md)
- [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0-rc3...v1.1.0-rc4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 14:17:14 +02:00
Guillaume Lours
8a64ab56a0 Merge pull request #10760 from docker/dependabot/go_modules/gotest.tools/v3-3.5.0
build(deps): bump gotest.tools/v3 from 3.4.0 to 3.5.0
2023-07-10 14:16:34 +02:00
dependabot[bot]
1178c51e6a build(deps): bump gotest.tools/v3 from 3.4.0 to 3.5.0
Bumps [gotest.tools/v3](https://github.com/gotestyourself/gotest.tools) from 3.4.0 to 3.5.0.
- [Release notes](https://github.com/gotestyourself/gotest.tools/releases)
- [Commits](https://github.com/gotestyourself/gotest.tools/compare/v3.4.0...v3.5.0)

---
updated-dependencies:
- dependency-name: gotest.tools/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 12:40:37 +02:00
dependabot[bot]
3b3fd3e56c build(deps): bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.2+incompatible to 24.0.4+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v24.0.2...v24.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 10:39:23 +00:00
Guillaume Lours
b1e10f559e Merge pull request #10781 from milas/deps-docs-0.6
deps: bump docker/cli-docs-tool to v0.6.0
2023-07-10 12:38:04 +02:00
Milas Bowman
baea5a48f5 deps: bump docker/cli-docs-tool to v0.6.0
Required re-running `make docs` to pick up changes.

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-07-10 12:23:48 +02:00
Guillaume Lours
cb3a6ce52b Merge pull request #10787 from docker/dependabot/go_modules/google.golang.org/grpc-1.56.2
build(deps): bump google.golang.org/grpc from 1.56.0 to 1.56.2
2023-07-10 12:23:25 +02:00
dependabot[bot]
28f3802a07 build(deps): bump google.golang.org/grpc from 1.56.0 to 1.56.2
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.56.0 to 1.56.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.56.0...v1.56.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-10 09:23:22 +00:00
Shan Desai
fd0e0a2cbd fix(secrets): file permission value does not comply with spec
closes #10783

Compose Spec mentions that default values for secrets is `0444` aka. world-readable permissions. However, the value was previously set to `0400`. 


Signed-off-by: Shan Desai <shantanoo.desai@gmail.com>
2023-07-07 18:58:21 +02:00
Guillaume Lours
e90df62bb0 Merge pull request #10763 from ndeloof/exec_index
when --index is not set select first service container
2023-07-07 14:39:50 +02:00
Nicolas De Loof
b0af2deb2b when --index is not set select first service container
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-07-07 14:08:24 +02:00
Milas Bowman
be22bc735a network: fix random missing network when service has more than one
As part of the fix for #10668, the logic was adjusted so that the
default (highest-priority) network is used in the `ContainerCreate`,
and then the remaining networks are connected via calls to
`NetworkConnect` before starting the container.

Unfortunately, `ServiceConfig::NetworksByPriority` is neither
deterministic nor stable when networks have the same priority.

It's non-deterministic because the order of networks from parsing
YAML is random, since they are loaded into a Go map (which have
random iteration order). Additionally, it's not using a `SortStable`
in `compose-go`, so even if the load order was predictable, it
still might produce different results.

While I look at improving `compose-go` here to prevent this from
tripping us up in the future, this fix looks at _all_ networks for
a service and ignores the "default" one now. Before, it would
always skip the first one in the slice since that _should_ have
been the "default".

Signed-off-by: Milas Bowman <milas.bowman@docker.com>
2023-07-07 09:18:01 +02:00
Nicolas De Loof
b5f5e27597 don't use unitialized cli to setup DryRunClient
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2023-07-06 14:27:57 +02:00
Guillaume Lours
b1334b8dfc Merge pull request #10768 from cloud-native-team/v2
fix some comments
2023-07-06 10:06:05 +02:00
cui fliter
25ca75db4d fix some comments
Signed-off-by: cui fliter <imcusg@gmail.com>
2023-07-04 11:34:49 +08:00
60 changed files with 218 additions and 455 deletions

View File

@@ -91,6 +91,7 @@ FROM build-base AS lint
ARG BUILD_TAGS
RUN --mount=type=bind,target=. \
--mount=type=cache,target=/root/.cache \
--mount=type=cache,target=/go/pkg/mod \
--mount=from=golangci-lint,source=/usr/bin/golangci-lint,target=/usr/bin/golangci-lint \
golangci-lint run --build-tags "$BUILD_TAGS" ./...
@@ -129,6 +130,7 @@ FROM base AS docsgen
WORKDIR /src
RUN --mount=target=. \
--mount=target=/root/.cache,type=cache \
--mount=type=cache,target=/go/pkg/mod \
go build -o /out/docsgen ./docs/yaml/main/generate.go
FROM --platform=${BUILDPLATFORM} alpine AS docs-build

View File

@@ -26,6 +26,7 @@ import (
"strings"
"syscall"
"github.com/compose-spec/compose-go/dotenv"
buildx "github.com/docker/buildx/util/progress"
"github.com/docker/cli/cli/command"
@@ -427,7 +428,6 @@ func RootCommand(streams command.Cli, backend api.Service) *cobra.Command { //no
imagesCommand(&opts, streams, backend),
versionCommand(streams),
buildCommand(&opts, &progress, backend),
publishCommand(&opts, backend),
pushCommand(&opts, backend),
pullCommand(&opts, backend),
createCommand(&opts, backend),
@@ -473,7 +473,7 @@ func setEnvWithDotEnv(prjOpts *ProjectOptions) error {
return err
}
envFromFile, err := cli.GetEnvFromFile(composegoutils.GetAsEqualsMap(os.Environ()), workingDir, options.EnvFiles)
envFromFile, err := dotenv.GetEnvFromFile(composegoutils.GetAsEqualsMap(os.Environ()), workingDir, options.EnvFiles)
if err != nil {
return err
}

View File

@@ -64,10 +64,10 @@ func copyCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
}
flags := copyCmd.Flags()
flags.IntVar(&opts.index, "index", 0, "Index of the container if there are multiple instances of a service .")
flags.BoolVar(&opts.all, "all", false, "Copy to all the containers of the service.")
flags.IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas")
flags.BoolVar(&opts.all, "all", false, "copy to all the containers of the service.")
flags.MarkHidden("all") //nolint:errcheck
flags.MarkDeprecated("all", "By default all the containers of the service will get the source file/directory to be copied.") //nolint:errcheck
flags.MarkDeprecated("all", "by default all the containers of the service will get the source file/directory to be copied.") //nolint:errcheck
flags.BoolVarP(&opts.followLink, "follow-link", "L", false, "Always follow symbol link in SRC_PATH")
flags.BoolVarP(&opts.copyUIDGID, "archive", "a", false, "Archive mode (copy all uid/gid information)")

View File

@@ -65,7 +65,7 @@ func execCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *c
runCmd.Flags().BoolVarP(&opts.detach, "detach", "d", false, "Detached mode: Run command in the background.")
runCmd.Flags().StringArrayVarP(&opts.environment, "env", "e", []string{}, "Set environment variables")
runCmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if there are multiple instances of a service [default: 1].")
runCmd.Flags().IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas")
runCmd.Flags().BoolVarP(&opts.privileged, "privileged", "", false, "Give extended privileges to the process.")
runCmd.Flags().StringVarP(&opts.user, "user", "u", "", "Run the command as this user.")
runCmd.Flags().BoolVarP(&opts.noTty, "no-TTY", "T", !streams.Out().IsTerminal(), "Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY.")

View File

@@ -57,7 +57,7 @@ func portCommand(p *ProjectOptions, streams api.Streams, backend api.Service) *c
ValidArgsFunction: completeServiceNames(p),
}
cmd.Flags().StringVar(&opts.protocol, "protocol", "tcp", "tcp or udp")
cmd.Flags().IntVar(&opts.index, "index", 1, "index of the container if service has multiple replicas")
cmd.Flags().IntVar(&opts.index, "index", 0, "index of the container if service has multiple replicas")
return cmd
}

View File

@@ -1,55 +0,0 @@
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package compose
import (
"context"
"github.com/spf13/cobra"
"github.com/docker/compose/v2/pkg/api"
)
type publishOptions struct {
*ProjectOptions
composeOptions
Repository string
}
func publishCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
opts := pushOptions{
ProjectOptions: p,
}
publishCmd := &cobra.Command{
Use: "publish [OPTIONS] [REPOSITORY]",
Short: "Publish compose application",
RunE: Adapt(func(ctx context.Context, args []string) error {
return runPublish(ctx, backend, opts, args[0])
}),
Args: cobra.ExactArgs(1),
}
return publishCmd
}
func runPublish(ctx context.Context, backend api.Service, opts pushOptions, repository string) error {
project, err := opts.ToProject(nil)
if err != nil {
return err
}
return backend.Publish(ctx, project, repository)
}

View File

@@ -31,7 +31,6 @@ type pushOptions struct {
IncludeDeps bool
Ignorefailures bool
Quiet bool
Repository string
}
func pushCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
@@ -49,7 +48,6 @@ func pushCommand(p *ProjectOptions, backend api.Service) *cobra.Command {
pushCmd.Flags().BoolVar(&opts.Ignorefailures, "ignore-push-failures", false, "Push what it can and ignores images with push failures")
pushCmd.Flags().BoolVar(&opts.IncludeDeps, "include-deps", false, "Also push images of services declared as dependencies")
pushCmd.Flags().BoolVarP(&opts.Quiet, "quiet", "q", false, "Push without printing progress information")
pushCmd.Flags().StringVarP(&opts.Repository, "repository", "r", "", "Also publish the compose application in repository")
return pushCmd
}
@@ -70,6 +68,5 @@ func runPush(ctx context.Context, backend api.Service, opts pushOptions, service
return backend.Push(ctx, project, api.PushOptions{
IgnoreFailures: opts.Ignorefailures,
Quiet: opts.Quiet,
Repository: opts.Repository,
})
}

View File

@@ -63,6 +63,13 @@ type runOptions struct {
}
func (options runOptions) apply(project *types.Project) error {
if options.noDeps {
err := project.ForServices([]string{options.Service}, types.IgnoreDependencies)
if err != nil {
return err
}
}
target, err := project.GetService(options.Service)
if err != nil {
return err
@@ -93,13 +100,6 @@ func (options runOptions) apply(project *types.Project) error {
}
}
if options.noDeps {
err := project.ForServices([]string{options.Service}, types.IgnoreDependencies)
if err != nil {
return err
}
}
for i, s := range project.Services {
if s.Name == options.Service {
project.Services[i] = target

View File

@@ -21,9 +21,8 @@ import (
"fmt"
"time"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/compose-spec/compose-go/types"
"github.com/docker/compose/v2/cmd/formatter"
"github.com/spf13/cobra"
"github.com/docker/compose/v2/pkg/api"
@@ -164,17 +163,31 @@ func runUp(ctx context.Context, streams api.Streams, backend api.Service, create
consumer = formatter.NewLogConsumer(ctx, streams.Out(), streams.Err(), !upOptions.noColor, !upOptions.noPrefix, upOptions.timestamp)
}
attachTo := services
attachTo := utils.Set[string]{}
if len(upOptions.attach) > 0 {
attachTo = upOptions.attach
attachTo.AddAll(upOptions.attach...)
}
if upOptions.attachDependencies {
attachTo = project.ServiceNames()
if err := project.WithServices(attachTo.Elements(), func(s types.ServiceConfig) error {
if s.Attach == nil || *s.Attach {
attachTo.Add(s.Name)
}
return nil
}); err != nil {
return err
}
}
if len(attachTo) == 0 {
attachTo = project.ServiceNames()
if err := project.WithServices(services, func(s types.ServiceConfig) error {
if s.Attach == nil || *s.Attach {
attachTo.Add(s.Name)
}
return nil
}); err != nil {
return err
}
}
attachTo = utils.Remove(attachTo, upOptions.noAttach...)
attachTo.RemoveAll(upOptions.noAttach...)
create := api.CreateOptions{
Services: services,
@@ -198,7 +211,7 @@ func runUp(ctx context.Context, streams api.Streams, backend api.Service, create
Start: api.StartOptions{
Project: project,
Attach: consumer,
AttachTo: attachTo,
AttachTo: attachTo.Elements(),
ExitCodeFrom: upOptions.exitCodeFrom,
CascadeStop: upOptions.cascadeStop,
Wait: upOptions.wait,

View File

@@ -7,7 +7,6 @@ Define and run multi-container applications with Docker.
| Name | Description |
|:--------------------------------|:------------------------------------------------------------------------|
| [`alpha`](compose_alpha.md) | Experimental commands |
| [`build`](compose_build.md) | Build or rebuild services |
| [`config`](compose_config.md) | Parse, resolve and render compose file in canonical format |
| [`cp`](compose_cp.md) | Copy files/folders between a service container and the local filesystem |

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 there are multiple instances of a service . |
| 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 |
<!---MARKER_GEN_END-->

View File

@@ -5,16 +5,16 @@ Execute a command in a running container.
### Options
| Name | Type | Default | Description |
|:------------------|:--------------|:--------|:----------------------------------------------------------------------------------|
| `-d`, `--detach` | | | Detached mode: Run command in the background. |
| `--dry-run` | | | Execute command in dry run mode |
| `-e`, `--env` | `stringArray` | | Set environment variables |
| `--index` | `int` | `1` | index of the container if there are multiple instances of a service [default: 1]. |
| `-T`, `--no-TTY` | | | Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY. |
| `--privileged` | | | Give extended privileges to the process. |
| `-u`, `--user` | `string` | | Run the command as this user. |
| `-w`, `--workdir` | `string` | | Path to workdir directory for this command. |
| Name | Type | Default | Description |
|:------------------|:--------------|:--------|:---------------------------------------------------------------------------------|
| `-d`, `--detach` | | | Detached mode: Run command in the background. |
| `--dry-run` | | | Execute command in dry run mode |
| `-e`, `--env` | `stringArray` | | Set environment variables |
| `--index` | `int` | `0` | index of the container if service has multiple replicas |
| `-T`, `--no-TTY` | | | Disable pseudo-TTY allocation. By default `docker compose exec` allocates a TTY. |
| `--privileged` | | | Give extended privileges to the process. |
| `-u`, `--user` | `string` | | Run the command as this user. |
| `-w`, `--workdir` | `string` | | Path to workdir directory for this command. |
<!---MARKER_GEN_END-->

View File

@@ -8,7 +8,7 @@ Print the public port for a port binding.
| Name | Type | Default | Description |
|:-------------|:---------|:--------|:--------------------------------------------------------|
| `--dry-run` | | | Execute command in dry run mode |
| `--index` | `int` | `1` | index of the container if service has multiple replicas |
| `--index` | `int` | `0` | index of the container if service has multiple replicas |
| `--protocol` | `string` | `tcp` | tcp or udp |

View File

@@ -347,6 +347,7 @@ options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -21,6 +21,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: true
experimental: false
experimentalcli: true
kubernetes: false

View File

@@ -69,6 +69,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: true
kubernetes: false

View File

@@ -29,6 +29,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: true
kubernetes: false

View File

@@ -159,6 +159,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -152,6 +152,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -10,7 +10,7 @@ options:
- option: all
value_type: bool
default_value: "false"
description: Copy to all the containers of the service.
description: copy to all the containers of the service.
deprecated: true
hidden: true
experimental: false
@@ -42,8 +42,7 @@ options:
- option: index
value_type: int
default_value: "0"
description: |
Index of the container if there are multiple instances of a service .
description: index of the container if service has multiple replicas
deprecated: false
hidden: false
experimental: false
@@ -62,6 +61,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -90,6 +90,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -73,6 +73,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -46,6 +46,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -33,9 +33,8 @@ options:
swarm: false
- option: index
value_type: int
default_value: "1"
description: |
index of the container if there are multiple instances of a service [default: 1].
default_value: "0"
description: index of the container if service has multiple replicas
deprecated: false
hidden: false
experimental: false
@@ -118,6 +117,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -38,6 +38,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -43,6 +43,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -91,6 +91,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -58,6 +58,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -17,6 +17,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -7,7 +7,7 @@ plink: docker_compose.yaml
options:
- option: index
value_type: int
default_value: "1"
default_value: "0"
description: index of the container if service has multiple replicas
deprecated: false
hidden: false
@@ -37,6 +37,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -180,6 +180,7 @@ examples: |-
The `docker compose ps` command currently only supports the `--filter status=<status>`
option, but additional filter options may be added in the future.
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -124,6 +124,7 @@ examples: |-
`docker compose pull` will try to pull image for services with a build section. If pull fails, it will let
user know this service image MUST be built. You can skip this by setting `--ignore-buildable` flag
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -66,6 +66,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -48,6 +48,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -76,6 +76,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -286,6 +286,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -16,6 +16,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -29,6 +29,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -23,6 +23,7 @@ examples: |-
root 142353 142331 2 15:33 ? 00:00:00 ping localhost -c 5
```
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -16,6 +16,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -285,6 +285,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -37,6 +37,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

View File

@@ -27,6 +27,7 @@ inherited_options:
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false

15
go.mod
View File

@@ -6,15 +6,15 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/Microsoft/go-winio v0.6.1
github.com/buger/goterm v1.0.4
github.com/compose-spec/compose-go v1.15.1
github.com/compose-spec/compose-go v1.16.0
github.com/containerd/console v1.0.3
github.com/containerd/containerd v1.7.2
github.com/cucumber/godog v0.0.0-00010101000000-000000000000 // replaced; see replace for the actual version used
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493
github.com/docker/buildx v0.11.0
github.com/docker/buildx v0.11.1
github.com/docker/cli v24.0.2+incompatible
github.com/docker/cli-docs-tool v0.5.1
github.com/docker/docker v24.0.2+incompatible
github.com/docker/cli-docs-tool v0.6.0
github.com/docker/docker v24.0.4+incompatible
github.com/docker/go-connections v0.4.0
github.com/docker/go-units v0.5.0
github.com/fsnotify/fsevents v0.1.1
@@ -44,9 +44,9 @@ require (
go.opentelemetry.io/otel/trace v1.14.0
go.uber.org/goleak v1.2.1
golang.org/x/sync v0.3.0
google.golang.org/grpc v1.56.0
google.golang.org/grpc v1.56.2
gopkg.in/yaml.v2 v2.4.0
gotest.tools/v3 v3.4.0
gotest.tools/v3 v3.5.0
)
require (
@@ -150,7 +150,7 @@ require (
github.com/subosito/gotenv v1.4.1 // indirect
github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f // indirect
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
@@ -183,7 +183,6 @@ require (
k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
oras.land/oras-go/v2 v2.2.0 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect

32
go.sum
View File

@@ -131,8 +131,8 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/compose-spec/compose-go v1.15.1 h1:0yaEt6/66dLN0bNWYDTj0CDx626uCdQ9ipJVIJx8O8M=
github.com/compose-spec/compose-go v1.15.1/go.mod h1:3yngGBGfls6FHGQsg4B1z6gz8ej9SOvmAJtxCwgbcnc=
github.com/compose-spec/compose-go v1.16.0 h1:HYk4uYWXgArHh6NG+WE4yGYayOXw+hjqJ+eJxpjWWjk=
github.com/compose-spec/compose-go v1.16.0/go.mod h1:3yngGBGfls6FHGQsg4B1z6gz8ej9SOvmAJtxCwgbcnc=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
@@ -167,17 +167,17 @@ github.com/denisenkom/go-mssqldb v0.0.0-20190515213511-eb9f6a1743f3/go.mod h1:zA
github.com/denisenkom/go-mssqldb v0.0.0-20191128021309-1d7a30a10f73/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493 h1:fm5DpBD+A7o0+x9Nf+o9/4/qPGbfxLpr9qIPVuV8vQc=
github.com/distribution/distribution/v3 v3.0.0-20230601133803-97b1d649c493/go.mod h1:+fqBJ4vPYo4Uu1ZE4d+bUtTLRXfdSL3NvCZIZ9GHv58=
github.com/docker/buildx v0.11.0 h1:DNCOIYT/7J0sPBlU/ozEhFd4MtbnbFByn45yeTMHXVU=
github.com/docker/buildx v0.11.0/go.mod h1:Yq7ZNjrwXKzW0uSFMk46dl5Gl903k5+bp6U4apsM5rs=
github.com/docker/buildx v0.11.1 h1:xfmrAkOJrN+NLRcwhZn1iBgJVAK1dEBEv8lWu1Wxg14=
github.com/docker/buildx v0.11.1/go.mod h1:qAxs3bsJEfVo7DOc9riES/f9Z187CeGM5nLPmadk8AA=
github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM=
github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.5.1 h1:jIk/cCZurZERhALPVKhqlNxTQGxn2kcI+56gE57PQXg=
github.com/docker/cli-docs-tool v0.5.1/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o=
github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA=
github.com/docker/cli-docs-tool v0.6.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg=
github.com/docker/docker v24.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.4+incompatible h1:s/LVDftw9hjblvqIeTiGYXBCD95nOEEl7qRsRrIOuQI=
github.com/docker/docker v24.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
@@ -511,8 +511,6 @@ github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0=
github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk=
@@ -632,8 +630,8 @@ github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576 h1:fZXPQDVh5fm2x
github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576/go.mod h1:q1CxMSzcAbjUkVGHoZeQUcCaALnaE4XdWk+zJcgMYFw=
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-20210615222946-8066bb97264f h1:DLpt6B5oaaS8jyXHa9VA4rrZloBVPVXeCtrOsrFauxc=
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc=
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 h1:Y/M5lygoNPKwVNLMPXgVfsRT40CSFKXCxuU8LoHySjs=
github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc=
github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236 h1:vMJBP3PQViZsF6cOINtvyMC8ptpLsyJ4EwyFnzuWNxc=
github.com/weppos/publicsuffix-go v0.15.1-0.20220329081811-9a40b608a236/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE=
@@ -1041,8 +1039,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.56.0 h1:+y7Bs8rtMd07LeXmL3NxcTLn7mUkbKZqEpPhMNkwJEE=
google.golang.org/grpc v1.56.0/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI=
google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1090,8 +1088,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -1112,8 +1110,6 @@ k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+O
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk=
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
oras.land/oras-go/v2 v2.2.0 h1:E1fqITD56Eg5neZbxBtAdZVgDHD6wBabJo6xESTcQyo=
oras.land/oras-go/v2 v2.2.0/go.mod h1:pXjn0+KfarspMHHNR3A56j3tgvr+mxArHuI8qVn59v8=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@@ -74,8 +74,6 @@ type Service interface {
Events(ctx context.Context, projectName string, options EventsOptions) error
// Port executes the equivalent to a `compose port`
Port(ctx context.Context, projectName string, service string, port uint16, options PortOptions) (string, int, error)
// Publish executes the equivalent to a `compose publish`
Publish(ctx context.Context, project *types.Project, repository string) error
// Images executes the equivalent of a `compose images`
Images(ctx context.Context, projectName string, options ImagesOptions) ([]ImageSummary, error)
// MaxConcurrency defines upper limit for concurrent operations against engine API
@@ -262,7 +260,6 @@ type ConfigOptions struct {
// PushOptions group options of the Push API
type PushOptions struct {
Quiet bool
Repository string
IgnoreFailures bool
}

View File

@@ -70,7 +70,7 @@ type execDetails struct {
}
// NewDryRunClient produces a DryRunClient
func NewDryRunClient(apiClient client.APIClient, cli *command.DockerCli) (*DryRunClient, error) {
func NewDryRunClient(apiClient client.APIClient, cli command.Cli) (*DryRunClient, error) {
b, err := builder.New(cli, builder.WithSkippedValidation())
if err != nil {
return nil, err

View File

@@ -55,7 +55,6 @@ type ServiceProxy struct {
DryRunModeFn func(ctx context.Context, dryRun bool) (context.Context, error)
VizFn func(ctx context.Context, project *types.Project, options VizOptions) (string, error)
WaitFn func(ctx context.Context, projectName string, options WaitOptions) (int64, error)
PublishFn func(ctx context.Context, project *types.Project, repository string) error
interceptors []Interceptor
}
@@ -92,7 +91,6 @@ func (s *ServiceProxy) WithService(service Service) *ServiceProxy {
s.TopFn = service.Top
s.EventsFn = service.Events
s.PortFn = service.Port
s.PublishFn = service.Publish
s.ImagesFn = service.Images
s.WatchFn = service.Watch
s.MaxConcurrencyFn = service.MaxConcurrency
@@ -219,7 +217,7 @@ func (s *ServiceProxy) List(ctx context.Context, options ListOptions) ([]Stack,
return s.ListFn(ctx, options)
}
// Convert implements Service interface
// Config implements Service interface
func (s *ServiceProxy) Config(ctx context.Context, project *types.Project, options ConfigOptions) ([]byte, error) {
if s.ConfigFn == nil {
return nil, ErrNotImplemented
@@ -313,10 +311,6 @@ func (s *ServiceProxy) Port(ctx context.Context, projectName string, service str
return s.PortFn(ctx, projectName, service, port, options)
}
func (s *ServiceProxy) Publish(ctx context.Context, project *types.Project, repository string) error {
return s.PublishFn(ctx, project, repository)
}
// Images implements Service interface
func (s *ServiceProxy) Images(ctx context.Context, project string, options ImagesOptions) ([]ImageSummary, error) {
if s.ImagesFn == nil {

View File

@@ -88,8 +88,11 @@ func (s *composeService) DryRunMode(ctx context.Context, dryRun bool) (context.C
if err != nil {
return ctx, err
}
err = cli.Initialize(flags.NewClientOptions(), command.WithInitializeClient(func(cli *command.DockerCli) (client.APIClient, error) {
return api.NewDryRunClient(s.apiClient(), cli)
options := flags.NewClientOptions()
options.Context = s.dockerCli.CurrentContext()
err = cli.Initialize(options, command.WithInitializeClient(func(cli *command.DockerCli) (client.APIClient, error) {
return api.NewDryRunClient(s.apiClient(), s.dockerCli)
}))
if err != nil {
return ctx, err

View File

@@ -20,6 +20,7 @@ import (
"context"
"fmt"
"sort"
"strconv"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/utils"
@@ -72,7 +73,9 @@ func getDefaultFilters(projectName string, oneOff oneOff, selectedServices ...st
func (s *composeService) getSpecifiedContainer(ctx context.Context, projectName string, oneOff oneOff, stopped bool, serviceName string, containerIndex int) (moby.Container, error) {
defaultFilters := getDefaultFilters(projectName, oneOff, serviceName)
defaultFilters = append(defaultFilters, containerNumberFilter(containerIndex))
if containerIndex > 0 {
defaultFilters = append(defaultFilters, containerNumberFilter(containerIndex))
}
containers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
Filters: filters.NewArgs(
defaultFilters...,
@@ -83,8 +86,16 @@ func (s *composeService) getSpecifiedContainer(ctx context.Context, projectName
return moby.Container{}, err
}
if len(containers) < 1 {
return moby.Container{}, fmt.Errorf("service %q is not running container #%d", serviceName, containerIndex)
if containerIndex > 0 {
return moby.Container{}, fmt.Errorf("service %q is not running container #%d", serviceName, containerIndex)
}
return moby.Container{}, fmt.Errorf("service %q is not running", serviceName)
}
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
})
container := containers[0]
return container, nil
}

View File

@@ -549,13 +549,15 @@ func (s *composeService) createMobyContainer(ctx context.Context,
// call via container.NetworkMode & network.NetworkingConfig
// any remaining networks are connected one-by-one here after creation (but before start)
serviceNetworks := service.NetworksByPriority()
if len(serviceNetworks) > 1 {
for _, networkKey := range serviceNetworks[1:] {
mobyNetworkName := project.Networks[networkKey].Name
epSettings := createEndpointSettings(project, service, number, networkKey, cfgs.Links, opts.UseNetworkAliases)
if err := s.apiClient().NetworkConnect(ctx, mobyNetworkName, created.ID, epSettings); err != nil {
return created, err
}
for _, networkKey := range serviceNetworks {
mobyNetworkName := project.Networks[networkKey].Name
if string(cfgs.Host.NetworkMode) == mobyNetworkName {
// primary network already configured as part of ContainerCreate
continue
}
epSettings := createEndpointSettings(project, service, number, networkKey, cfgs.Links, opts.UseNetworkAliases)
if err := s.apiClient().NetworkConnect(ctx, mobyNetworkName, created.ID, epSettings); err != nil {
return created, err
}
}

View File

@@ -24,25 +24,14 @@ import (
"github.com/docker/compose/v2/pkg/api"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
)
func (s *composeService) Port(ctx context.Context, projectName string, service string, port uint16, options api.PortOptions) (string, int, error) {
projectName = strings.ToLower(projectName)
list, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
Filters: filters.NewArgs(
projectFilter(projectName),
serviceFilter(service),
containerNumberFilter(options.Index),
),
})
container, err := s.getSpecifiedContainer(ctx, projectName, oneOffInclude, false, service, options.Index)
if err != nil {
return "", 0, err
}
if len(list) == 0 {
return "", 0, fmt.Errorf("no container found for %s%s%d", service, api.Separator, options.Index)
}
container := list[0]
for _, p := range container.Ports {
if p.PrivatePort == port && p.Type == options.Protocol {
return p.IP, int(p.PublicPort), nil

View File

@@ -1,185 +0,0 @@
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package compose
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"os/exec"
"strings"
"github.com/compose-spec/compose-go/types"
"github.com/distribution/distribution/v3/reference"
client2 "github.com/docker/cli/cli/registry/client"
"github.com/docker/compose/v2/pkg/api"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)
func (s *composeService) Publish(ctx context.Context, project *types.Project, repository string) error {
err := s.Push(ctx, project, api.PushOptions{})
if err != nil {
return err
}
target, err := reference.ParseDockerRef(repository)
if err != nil {
return err
}
client := s.dockerCli.RegistryClient(false)
for i, service := range project.Services {
ref, err := reference.ParseDockerRef(service.Image)
if err != nil {
return err
}
auth, err := encodedAuth(ref, s.configFile())
if err != nil {
return err
}
inspect, err := s.apiClient().DistributionInspect(ctx, ref.String(), auth)
if err != nil {
return err
}
canonical, err := reference.WithDigest(ref, inspect.Descriptor.Digest)
if err != nil {
return err
}
to, err := reference.WithDigest(target, inspect.Descriptor.Digest)
if err != nil {
return err
}
err = client.MountBlob(ctx, canonical, to)
switch err.(type) {
case client2.ErrBlobCreated:
default:
return err
}
service.Image = to.String()
project.Services[i] = service
}
err = s.publishComposeYaml(ctx, project, repository)
if err != nil {
return err
}
return nil
}
func (s *composeService) publishComposeYaml(ctx context.Context, project *types.Project, repository string) error {
ref, err := reference.ParseDockerRef(repository)
if err != nil {
return err
}
var manifests []v1.Descriptor
for _, composeFile := range project.ComposeFiles {
stat, err := os.Stat(composeFile)
if err != nil {
return err
}
cmd := exec.CommandContext(ctx, "oras", "push", "--artifact-type", "application/vnd.docker.compose.yaml", ref.String(), composeFile)
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}
cmd.Stderr = s.stderr()
err = cmd.Start()
if err != nil {
return err
}
out, err := io.ReadAll(stdout)
if err != nil {
return err
}
var composeFileDigest string
for _, line := range strings.Split(string(out), "\n") {
if strings.HasPrefix(line, "Digest: ") {
composeFileDigest = line[len("Digest: "):]
}
fmt.Fprintln(s.stdout(), line)
}
if composeFileDigest == "" {
return fmt.Errorf("expected oras to display `Digest: xxx`")
}
err = cmd.Wait()
if err != nil {
return err
}
manifests = append(manifests, v1.Descriptor{
MediaType: "application/vnd.oci.image.manifest.v1+json",
Digest: digest.Digest(composeFileDigest),
Size: stat.Size(),
ArtifactType: "application/vnd.docker.compose.yaml",
})
}
for _, service := range project.Services {
dockerRef, err := reference.ParseDockerRef(service.Image)
if err != nil {
return err
}
manifests = append(manifests, v1.Descriptor{
MediaType: v1.MediaTypeImageIndex,
Digest: dockerRef.(reference.Digested).Digest(),
Annotations: map[string]string{
"com.docker.compose.service": service.Name,
},
})
}
manifest := v1.Index{
Versioned: specs.Versioned{
SchemaVersion: 2,
},
MediaType: v1.MediaTypeImageIndex,
Manifests: manifests,
Annotations: map[string]string{
"com.docker.compose": api.ComposeVersion,
},
}
manifestContent, err := json.Marshal(manifest)
if err != nil {
return err
}
temp, err := os.CreateTemp(os.TempDir(), "compose")
if err != nil {
return err
}
err = os.WriteFile(temp.Name(), manifestContent, 0o700)
if err != nil {
return err
}
defer os.Remove(temp.Name())
cmd := exec.CommandContext(ctx, "oras", "manifest", "push", ref.String(), temp.Name())
cmd.Stdout = s.stdout()
cmd.Stderr = s.stderr()
err = cmd.Run()
if err != nil {
return err
}
return nil
}

View File

@@ -17,7 +17,6 @@
package compose
import (
"bytes"
"context"
"encoding/base64"
"encoding/json"
@@ -27,17 +26,14 @@ import (
"github.com/compose-spec/compose-go/types"
"github.com/distribution/distribution/v3/reference"
"github.com/docker/buildx/driver"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
moby "github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/docker/docker/registry"
"github.com/opencontainers/go-digest"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"oras.land/oras-go/v2/content"
"oras.land/oras-go/v2/registry/remote"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
)
func (s *composeService) Push(ctx context.Context, project *types.Project, options api.PushOptions) error {
@@ -49,8 +45,8 @@ func (s *composeService) Push(ctx context.Context, project *types.Project, optio
}, s.stdinfo(), "Pushing")
}
func (s *composeService) push(upctx context.Context, project *types.Project, options api.PushOptions) error {
eg, ctx := errgroup.WithContext(upctx)
func (s *composeService) push(ctx context.Context, project *types.Project, options api.PushOptions) error {
eg, ctx := errgroup.WithContext(ctx)
eg.SetLimit(s.maxConcurrency)
info, err := s.apiClient().Info(ctx)
@@ -83,66 +79,7 @@ func (s *composeService) push(upctx context.Context, project *types.Project, opt
return nil
})
}
err = eg.Wait()
if err != nil {
return err
}
ctx = upctx
if options.Repository != "" {
repository, err := remote.NewRepository(options.Repository)
if err != nil {
return err
}
yaml, err := project.MarshalYAML()
if err != nil {
return err
}
manifests := []v1.Descriptor{
{
MediaType: "application/vnd.oci.artifact.manifest.v1+json",
Digest: digest.FromBytes(yaml),
Size: int64(len(yaml)),
Data: yaml,
ArtifactType: "application/vnd.docker.compose.yaml",
},
}
for _, service := range project.Services {
inspected, _, err := s.dockerCli.Client().ImageInspectWithRaw(ctx, service.Image)
if err != nil {
return err
}
manifests = append(manifests, v1.Descriptor{
MediaType: v1.MediaTypeImageIndex,
Digest: digest.Digest(inspected.RepoDigests[0]),
Size: inspected.Size,
Annotations: map[string]string{
"com.docker.compose.service": service.Name,
},
})
}
manifest := v1.Index{
MediaType: v1.MediaTypeImageIndex,
Manifests: manifests,
Annotations: map[string]string{
"com.docker.compose": api.ComposeVersion,
},
}
manifestContent, err := json.Marshal(manifest)
if err != nil {
return err
}
manifestDescriptor := content.NewDescriptorFromBytes(v1.MediaTypeImageIndex, manifestContent)
err = repository.Push(ctx, manifestDescriptor, bytes.NewReader(manifestContent))
if err != nil {
return err
}
}
return nil
return eg.Wait()
}
func (s *composeService) pushServiceImage(ctx context.Context, service types.ServiceConfig, info moby.Info, configFile driver.Auth, w progress.Writer, quietPush bool) error {

View File

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

View File

@@ -136,4 +136,12 @@ func TestLocalComposeRun(t *testing.T) {
c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/deps.yaml", "down", "--remove-orphans")
})
t.Run("run without dependencies", func(t *testing.T) {
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/deps.yaml", "run", "--no-deps", "service_a")
assert.Assert(t, !strings.Contains(res.Combined(), "shared_dep"), res.Combined())
assert.Assert(t, !strings.Contains(res.Combined(), "service_b"), res.Combined())
c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/deps.yaml", "down", "--remove-orphans")
})
}

View File

@@ -29,47 +29,34 @@ import (
func TestNetworks(t *testing.T) {
// fixture is shared with TestNetworkModes and is not safe to run concurrently
c := NewCLI(t)
const projectName = "network-e2e"
c := NewCLI(t, WithEnv(
"COMPOSE_PROJECT_NAME="+projectName,
"COMPOSE_FILE=./fixtures/network-test/compose.yaml",
))
t.Run("ensure we do not reuse previous networks", func(t *testing.T) {
c.RunDockerOrExitError(t, "network", "rm", projectName+"-dbnet")
c.RunDockerOrExitError(t, "network", "rm", "microservices")
})
c.RunDockerComposeCmd(t, "down", "-t0", "-v")
t.Run("up", func(t *testing.T) {
c.RunDockerComposeCmd(t, "-f", "./fixtures/network-test/compose.yaml", "--project-name", projectName, "up",
"-d")
})
c.RunDockerComposeCmd(t, "up", "-d")
t.Run("check running project", func(t *testing.T) {
res := c.RunDockerComposeCmd(t, "-p", projectName, "ps")
res.Assert(t, icmd.Expected{Out: `web`})
res := c.RunDockerComposeCmd(t, "ps")
res.Assert(t, icmd.Expected{Out: `web`})
endpoint := "http://localhost:80"
output := HTTPGetWithRetry(t, endpoint+"/words/noun", http.StatusOK, 2*time.Second, 20*time.Second)
assert.Assert(t, strings.Contains(output, `"word":`))
endpoint := "http://localhost:80"
output := HTTPGetWithRetry(t, endpoint+"/words/noun", http.StatusOK, 2*time.Second, 20*time.Second)
assert.Assert(t, strings.Contains(output, `"word":`))
res = c.RunDockerCmd(t, "network", "ls")
res.Assert(t, icmd.Expected{Out: projectName + "_dbnet"})
res.Assert(t, icmd.Expected{Out: "microservices"})
})
res = c.RunDockerCmd(t, "network", "ls")
res.Assert(t, icmd.Expected{Out: projectName + "_dbnet"})
res.Assert(t, icmd.Expected{Out: "microservices"})
t.Run("port", func(t *testing.T) {
res := c.RunDockerComposeCmd(t, "--project-name", projectName, "port", "words", "8080")
res.Assert(t, icmd.Expected{Out: `0.0.0.0:8080`})
})
res = c.RunDockerComposeCmd(t, "port", "words", "8080")
res.Assert(t, icmd.Expected{Out: `0.0.0.0:8080`})
t.Run("down", func(t *testing.T) {
_ = c.RunDockerComposeCmd(t, "--project-name", projectName, "down")
})
t.Run("check networks after down", func(t *testing.T) {
res := c.RunDockerCmd(t, "network", "ls")
assert.Assert(t, !strings.Contains(res.Combined(), projectName), res.Combined())
assert.Assert(t, !strings.Contains(res.Combined(), "microservices"), res.Combined())
})
c.RunDockerComposeCmd(t, "down", "-t0", "-v")
res = c.RunDockerCmd(t, "network", "ls")
assert.Assert(t, !strings.Contains(res.Combined(), projectName), res.Combined())
assert.Assert(t, !strings.Contains(res.Combined(), "microservices"), res.Combined())
}
func TestNetworkAliases(t *testing.T) {

View File

@@ -21,6 +21,8 @@ import (
"testing"
"time"
"gotest.tools/v3/icmd"
"gotest.tools/v3/assert"
)
@@ -28,6 +30,12 @@ func TestWaitOnFaster(t *testing.T) {
const projectName = "e2e-wait-faster"
c := NewParallelCLI(t)
cleanup := func() {
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--timeout=0", "--remove-orphans")
}
t.Cleanup(cleanup)
cleanup()
c.RunDockerComposeCmd(t, "-f", "./fixtures/wait/compose.yaml", "--project-name", projectName, "up", "-d")
c.RunDockerComposeCmd(t, "--project-name", projectName, "wait", "faster")
}
@@ -36,6 +44,12 @@ func TestWaitOnSlower(t *testing.T) {
const projectName = "e2e-wait-slower"
c := NewParallelCLI(t)
cleanup := func() {
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--timeout=0", "--remove-orphans")
}
t.Cleanup(cleanup)
cleanup()
c.RunDockerComposeCmd(t, "-f", "./fixtures/wait/compose.yaml", "--project-name", projectName, "up", "-d")
c.RunDockerComposeCmd(t, "--project-name", projectName, "wait", "slower")
}
@@ -44,12 +58,27 @@ func TestWaitOnInfinity(t *testing.T) {
const projectName = "e2e-wait-infinity"
c := NewParallelCLI(t)
cleanup := func() {
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--timeout=0", "--remove-orphans")
}
t.Cleanup(cleanup)
cleanup()
c.RunDockerComposeCmd(t, "-f", "./fixtures/wait/compose.yaml", "--project-name", projectName, "up", "-d")
cmd := c.NewDockerComposeCmd(t, "--project-name", projectName, "wait", "infinity")
r := icmd.StartCmd(cmd)
assert.NilError(t, r.Error)
t.Cleanup(func() {
if r.Cmd.Process != nil {
_ = r.Cmd.Process.Kill()
}
})
finished := make(chan struct{})
ticker := time.NewTicker(7 * time.Second)
go func() {
c.RunDockerComposeCmd(t, "--project-name", projectName, "wait", "infinity")
_ = r.Cmd.Wait()
finished <- struct{}{}
}()
@@ -64,6 +93,12 @@ func TestWaitAndDrop(t *testing.T) {
const projectName = "e2e-wait-and-drop"
c := NewParallelCLI(t)
cleanup := func() {
c.RunDockerComposeCmd(t, "--project-name", projectName, "down", "--timeout=0", "--remove-orphans")
}
t.Cleanup(cleanup)
cleanup()
c.RunDockerComposeCmd(t, "-f", "./fixtures/wait/compose.yaml", "--project-name", projectName, "up", "-d")
c.RunDockerComposeCmd(t, "--project-name", projectName, "wait", "--down-project", "faster")

View File

@@ -47,3 +47,9 @@ func (s Set[T]) Elements() []T {
}
return elements
}
func (s Set[T]) RemoveAll(elements ...T) {
for _, e := range elements {
s.Remove(e)
}
}

View File

@@ -29,7 +29,7 @@ func Contains[T any](origin []T, element T) bool {
return false
}
// RemoveAll removes all elements from origin slice
// Remove removes all elements from origin slice
func Remove[T any](origin []T, elements ...T) []T {
var filtered []T
for _, v := range origin {