Ver código fonte

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

Vedant Koditkar 3 anos atrás
pai
commit
b96b5449e5

+ 6 - 0
.github/workflows/ci.yml

@@ -195,6 +195,12 @@ jobs:
         with:
           name: compose
           path: ${{ env.DESTDIR }}
+      -
+        name: Create checksums
+        working-directory: ${{ env.DESTDIR }}
+        run: |
+          find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# .*/#  #' > checksums.txt
+          shasum -a 256 -U -c checksums.txt
       -
         name: License
         run: cp packaging/* ${{ env.DESTDIR }}/

+ 1 - 3
Dockerfile

@@ -167,7 +167,6 @@ COPY --link --from=build /usr/bin/docker-compose /docker-compose.exe
 FROM binary-$TARGETOS AS binary
 
 FROM --platform=$BUILDPLATFORM alpine AS releaser
-RUN apk add --no-cache file perl-utils
 WORKDIR /work
 ARG TARGETOS
 ARG TARGETARCH
@@ -177,8 +176,7 @@ RUN --mount=from=binary \
     # TODO: should just use standard arch
     TARGETARCH=$([ "$TARGETARCH" = "amd64" ] && echo "x86_64" || echo "$TARGETARCH"); \
     TARGETARCH=$([ "$TARGETARCH" = "arm64" ] && echo "aarch64" || echo "$TARGETARCH"); \
-    cp docker-compose* "/out/docker-compose-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}$(ls docker-compose* | sed -e 's/^docker-compose//')" && \
-    (cd /out ; for f in *; do shasum --binary --algorithm 256 $f | tee -a /out/checksums.txt > $f.sha256; done)
+    cp docker-compose* "/out/docker-compose-${TARGETOS}-${TARGETARCH}${TARGETVARIANT}$(ls docker-compose* | sed -e 's/^docker-compose//')"
 
 FROM scratch AS release
 COPY --from=releaser /out/ /

+ 18 - 2
cmd/compose/compose.go

@@ -32,6 +32,8 @@ import (
 	dockercli "github.com/docker/cli/cli"
 	"github.com/docker/cli/cli-plugins/manager"
 	"github.com/docker/cli/cli/command"
+	"github.com/docker/cli/cli/flags"
+	"github.com/docker/docker/client"
 	"github.com/morikuni/aec"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -291,6 +293,18 @@ func RootCommand(dockerCli command.Cli, backend api.Service) *cobra.Command {
 			if err != nil {
 				return err
 			}
+
+			// Reset DockerCli and APIClient to get possible `DOCKER_HOST` and/or `DOCKER_CONTEXT` loaded from environment file.
+			err = dockerCli.Apply(func(cli *command.DockerCli) error {
+				return cli.Initialize(flags.NewClientOptions(),
+					command.WithInitializeClient(func(_ *command.DockerCli) (client.APIClient, error) {
+						return nil, nil
+					}))
+			})
+			if err != nil {
+				return err
+			}
+
 			parent := cmd.Root()
 			if parent != nil {
 				parentPrerun := parent.PersistentPreRunE
@@ -383,8 +397,10 @@ func setEnvWithDotEnv(prjOpts *projectOptions) error {
 		return err
 	}
 	for k, v := range envFromFile {
-		if err := os.Setenv(k, v); err != nil { // overwrite the process env with merged OS + env file results
-			return err
+		if _, ok := os.LookupEnv(k); !ok { // Precedence to OS Env
+			if err := os.Setenv(k, v); err != nil {
+				return err
+			}
 		}
 	}
 	return nil

+ 3 - 1
docker-bake.hcl

@@ -100,8 +100,10 @@ target "binary-cross" {
     "linux/arm/v7",
     "linux/arm64",
     "linux/ppc64le",
+    "linux/riscv64",
     "linux/s390x",
-    "windows/amd64"
+    "windows/amd64",
+    "windows/arm64"
   ]
 }
 

+ 3 - 3
go.mod

@@ -6,7 +6,7 @@ require (
 	github.com/AlecAivazis/survey/v2 v2.3.5
 	github.com/buger/goterm v1.0.4
 	github.com/cnabio/cnab-to-oci v0.3.6
-	github.com/compose-spec/compose-go v1.4.0
+	github.com/compose-spec/compose-go v1.5.0
 	github.com/containerd/console v1.0.3
 	github.com/containerd/containerd v1.6.8
 	github.com/distribution/distribution/v3 v3.0.0-20220729163034-26163d82560f
@@ -19,7 +19,7 @@ require (
 	github.com/golang/mock v1.6.0
 	github.com/hashicorp/go-multierror v1.1.1
 	github.com/hashicorp/go-version v1.6.0
-	github.com/mattn/go-isatty v0.0.14
+	github.com/mattn/go-isatty v0.0.16
 	github.com/mattn/go-shellwords v1.0.12
 	github.com/moby/buildkit v0.10.3
 	github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
@@ -111,7 +111,7 @@ require (
 	golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect
 	golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
 	golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
-	golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
+	golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
 	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect

+ 6 - 4
go.sum

@@ -286,8 +286,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC
 github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
 github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
 github.com/compose-spec/compose-go v1.2.1/go.mod h1:pAy7Mikpeft4pxkFU565/DRHEbDfR84G6AQuiL+Hdg8=
-github.com/compose-spec/compose-go v1.4.0 h1:zaYVAZ6lIByr7Jffi20AabfeUwcTrdXfH3X1R5HEm+g=
-github.com/compose-spec/compose-go v1.4.0/go.mod h1:l7RUULbFFLzlQHuxtJr7SVLyWdqEpbJEGTWCgcu6Eqw=
+github.com/compose-spec/compose-go v1.5.0 h1:yOmYpIm13pYt2o+oKVe/JAD6o2Tv+eUyOcRhf0qF4fA=
+github.com/compose-spec/compose-go v1.5.0/go.mod h1:l7RUULbFFLzlQHuxtJr7SVLyWdqEpbJEGTWCgcu6Eqw=
 github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
 github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
 github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
@@ -971,8 +971,9 @@ github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
 github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
 github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
 github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
 github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
@@ -1795,8 +1796,9 @@ golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

+ 2 - 2
pkg/api/proxy.go

@@ -22,6 +22,8 @@ import (
 	"github.com/compose-spec/compose-go/types"
 )
 
+var _ Service = &ServiceProxy{}
+
 // ServiceProxy implements Service by delegating to implementation functions. This allows lazy init and per-method overrides
 type ServiceProxy struct {
 	BuildFn              func(ctx context.Context, project *types.Project, options BuildOptions) error
@@ -59,8 +61,6 @@ func NewServiceProxy() *ServiceProxy {
 // Interceptor allow to customize the compose types.Project before the actual Service method is executed
 type Interceptor func(ctx context.Context, project *types.Project)
 
-var _ Service = &ServiceProxy{}
-
 // WithService configure proxy to use specified Service as delegate
 func (s *ServiceProxy) WithService(service Service) *ServiceProxy {
 	s.BuildFn = service.Build

+ 6 - 0
pkg/compose/convergence.go

@@ -352,6 +352,12 @@ func shouldWaitForDependency(serviceName string, dependencyConfig types.ServiceD
 		return false, nil
 	}
 	if service, err := project.GetService(serviceName); err != nil {
+		for _, ds := range project.DisabledServices {
+			if ds.Name == serviceName {
+				// don't wait for disabled service (--no-deps)
+				return false, nil
+			}
+		}
 		return false, err
 	} else if service.Scale == 0 {
 		// don't wait for the dependency which configured to have 0 containers running

+ 13 - 6
pkg/compose/create.go

@@ -146,6 +146,9 @@ func prepareNetworks(project *types.Project) {
 }
 
 func prepareServicesDependsOn(p *types.Project) error {
+	allServices := types.Project{}
+	allServices.Services = p.AllServices()
+
 	for i, service := range p.Services {
 		var dependencies []string
 		networkDependency := getDependentServiceFromMode(service.NetworkMode)
@@ -178,20 +181,24 @@ func prepareServicesDependsOn(p *types.Project) error {
 			dependencies = append(dependencies, strings.Split(link, ":")[0])
 		}
 
+		for d := range service.DependsOn {
+			dependencies = append(dependencies, d)
+		}
+
 		if len(dependencies) == 0 {
 			continue
 		}
-		if service.DependsOn == nil {
-			service.DependsOn = make(types.DependsOnConfig)
-		}
 
 		// Verify dependencies exist in the project, whether disabled or not
-		projAllServices := types.Project{}
-		projAllServices.Services = p.AllServices()
-		deps, err := projAllServices.GetServices(dependencies...)
+		deps, err := allServices.GetServices(dependencies...)
 		if err != nil {
 			return err
 		}
+
+		if service.DependsOn == nil {
+			service.DependsOn = make(types.DependsOnConfig)
+		}
+
 		for _, d := range deps {
 			if _, ok := service.DependsOn[d.Name]; !ok {
 				service.DependsOn[d.Name] = types.ServiceDependency{

+ 4 - 4
pkg/e2e/compose_environment_test.go

@@ -34,7 +34,7 @@ func TestEnvPriority(t *testing.T) {
 	})
 
 	// Full options activated
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment patched by --env-file)
+	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From OS Environment)
 	// 2. Compose File (service::environment section)
 	// 3. Compose File (service::env_file section file)
 	// 4. Container Image ENV directive
@@ -45,7 +45,7 @@ func TestEnvPriority(t *testing.T) {
 			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
 		cmd.Env = append(cmd.Env, "WHEREAMI=shell")
 		res := icmd.RunCmd(cmd)
-		assert.Equal(t, strings.TrimSpace(res.Stdout()), "override")
+		assert.Equal(t, strings.TrimSpace(res.Stdout()), "shell")
 	})
 
 	// Full options activated
@@ -63,7 +63,7 @@ func TestEnvPriority(t *testing.T) {
 	})
 
 	// No Compose file, all other options
-	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From environment patched by --env-file)
+	// 1. Command Line (docker compose run --env <KEY[=VAL]>)  <-- Result expected (From OS Environment)
 	// 2. Compose File (service::environment section)
 	// 3. Compose File (service::env_file section file)
 	// 4. Container Image ENV directive
@@ -74,7 +74,7 @@ func TestEnvPriority(t *testing.T) {
 			"run", "--rm", "-e", "WHEREAMI", "env-compose-priority")
 		cmd.Env = append(cmd.Env, "WHEREAMI=shell")
 		res := icmd.RunCmd(cmd)
-		assert.Equal(t, strings.TrimSpace(res.Stdout()), "override")
+		assert.Equal(t, strings.TrimSpace(res.Stdout()), "shell")
 	})
 
 	// No Compose file, all other options with env variable from OS environment

+ 15 - 0
pkg/e2e/fixtures/dependencies/recreate-no-deps.yaml

@@ -0,0 +1,15 @@
+version: '3.8'
+services:
+  my-service:
+    image: alpine
+    command: tail -f /dev/null
+    depends_on:
+      nginx: {condition: service_healthy}
+
+  nginx:
+    image: nginx:alpine
+    healthcheck:
+      test:     "echo | nc -w 5 localhost:80"
+      interval: 2s
+      timeout:  1s
+      retries:  10

+ 39 - 0
pkg/e2e/recreate_no_deps_test.go

@@ -0,0 +1,39 @@
+/*
+   Copyright 2022 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 (
+	"testing"
+
+	"gotest.tools/v3/icmd"
+)
+
+func TestRecreateWithNoDeps(t *testing.T) {
+	c := NewParallelCLI(t, WithEnv(
+		"COMPOSE_PROJECT_NAME=recreate-no-deps",
+	))
+
+	res := c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/dependencies/recreate-no-deps.yaml", "up", "-d")
+	res.Assert(t, icmd.Success)
+
+	res = c.RunDockerComposeCmdNoCheck(t, "-f", "fixtures/dependencies/recreate-no-deps.yaml", "up", "-d", "--force-recreate", "--no-deps", "my-service")
+	res.Assert(t, icmd.Success)
+
+	RequireServiceState(t, c, "my-service", "running")
+
+	c.RunDockerComposeCmd(t, "down")
+}