浏览代码

adopt compose-go/v2

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 1 年之前
父节点
当前提交
cda04f288e
共有 62 个文件被更改,包括 187 次插入144 次删除
  1. 11 4
      cmd/compose/build.go
  2. 4 4
      cmd/compose/compose.go
  3. 1 1
      cmd/compose/compose_test.go
  4. 2 2
      cmd/compose/config.go
  5. 11 3
      cmd/compose/create.go
  6. 1 1
      cmd/compose/create_test.go
  7. 1 1
      cmd/compose/exec.go
  8. 1 1
      cmd/compose/options.go
  9. 1 1
      cmd/compose/options_test.go
  10. 1 1
      cmd/compose/pull.go
  11. 1 1
      cmd/compose/pullOptions_test.go
  12. 1 1
      cmd/compose/push.go
  13. 4 4
      cmd/compose/run.go
  14. 5 5
      cmd/compose/scale.go
  15. 5 5
      cmd/compose/up.go
  16. 12 4
      cmd/compose/up_test.go
  17. 1 1
      cmd/compose/watch.go
  18. 1 1
      go.mod
  19. 2 2
      go.sum
  20. 3 3
      internal/sync/docker_cp.go
  21. 1 1
      internal/sync/shared.go
  22. 1 1
      internal/sync/tar.go
  23. 1 1
      internal/tracing/attributes.go
  24. 1 1
      pkg/api/api.go
  25. 1 1
      pkg/api/api_test.go
  26. 1 1
      pkg/api/proxy.go
  27. 1 1
      pkg/compose/attach.go
  28. 1 1
      pkg/compose/build.go
  29. 1 1
      pkg/compose/build_classic.go
  30. 17 7
      pkg/compose/compose.go
  31. 1 1
      pkg/compose/containers.go
  32. 7 4
      pkg/compose/convergence.go
  33. 15 13
      pkg/compose/convergence_test.go
  34. 1 1
      pkg/compose/convert.go
  35. 6 6
      pkg/compose/create.go
  36. 1 1
      pkg/compose/create_test.go
  37. 1 1
      pkg/compose/dependencies.go
  38. 1 1
      pkg/compose/dependencies_test.go
  39. 3 3
      pkg/compose/down.go
  40. 1 1
      pkg/compose/down_test.go
  41. 1 1
      pkg/compose/errors.go
  42. 5 6
      pkg/compose/hash.go
  43. 3 3
      pkg/compose/hash_test.go
  44. 1 1
      pkg/compose/image_pruner.go
  45. 1 1
      pkg/compose/logs_test.go
  46. 7 6
      pkg/compose/publish.go
  47. 1 1
      pkg/compose/pull.go
  48. 1 1
      pkg/compose/push.go
  49. 1 1
      pkg/compose/restart.go
  50. 3 2
      pkg/compose/run.go
  51. 1 1
      pkg/compose/scale.go
  52. 1 1
      pkg/compose/secrets.go
  53. 1 1
      pkg/compose/start.go
  54. 1 1
      pkg/compose/up.go
  55. 6 6
      pkg/compose/viz.go
  56. 1 1
      pkg/compose/viz_test.go
  57. 1 1
      pkg/compose/watch.go
  58. 1 1
      pkg/compose/watch_test.go
  59. 13 9
      pkg/e2e/scale_test.go
  60. 1 1
      pkg/mocks/mock_docker_compose_api.go
  61. 3 3
      pkg/remote/git.go
  62. 1 1
      pkg/remote/oci.go

+ 11 - 4
cmd/compose/build.go

@@ -22,9 +22,9 @@ import (
 	"os"
 	"strings"
 
-	"github.com/compose-spec/compose-go/cli"
-	"github.com/compose-spec/compose-go/loader"
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/cli"
+	"github.com/compose-spec/compose-go/v2/loader"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/command"
 	cliopts "github.com/docker/cli/opts"
 	ui "github.com/docker/compose/v2/pkg/progress"
@@ -50,7 +50,14 @@ func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions,
 	var SSHKeys []types.SSHKey
 	var err error
 	if opts.ssh != "" {
-		SSHKeys, err = loader.ParseShortSSHSyntax(opts.ssh)
+		id, path, found := strings.Cut(opts.ssh, "=")
+		if !found && id != "default" {
+			return api.BuildOptions{}, fmt.Errorf("invalid ssh key %q", opts.ssh)
+		}
+		SSHKeys = append(SSHKeys, types.SSHKey{
+			ID:   id,
+			Path: path,
+		})
 		if err != nil {
 			return api.BuildOptions{}, err
 		}

+ 4 - 4
cmd/compose/compose.go

@@ -27,10 +27,10 @@ import (
 	"strings"
 	"syscall"
 
-	"github.com/compose-spec/compose-go/cli"
-	"github.com/compose-spec/compose-go/dotenv"
-	"github.com/compose-spec/compose-go/types"
-	composegoutils "github.com/compose-spec/compose-go/utils"
+	"github.com/compose-spec/compose-go/v2/cli"
+	"github.com/compose-spec/compose-go/v2/dotenv"
+	"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"

+ 1 - 1
cmd/compose/compose_test.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"gotest.tools/v3/assert"
 )
 

+ 2 - 2
cmd/compose/config.go

@@ -24,8 +24,8 @@ import (
 	"sort"
 	"strings"
 
-	"github.com/compose-spec/compose-go/cli"
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/cli"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/spf13/cobra"
 

+ 11 - 3
cmd/compose/create.go

@@ -24,7 +24,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/spf13/cobra"
 
@@ -164,7 +164,15 @@ func (opts createOptions) Apply(project *types.Project) error {
 		return err
 	}
 
-	for _, scale := range opts.scale {
+	err := applyScaleOpts(project, opts.scale)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+func applyScaleOpts(project *types.Project, opts []string) error {
+	for _, scale := range opts {
 		split := strings.Split(scale, "=")
 		if len(split) != 2 {
 			return fmt.Errorf("invalid --scale option %q. Should be SERVICE=NUM", scale)
@@ -174,7 +182,7 @@ func (opts createOptions) Apply(project *types.Project) error {
 		if err != nil {
 			return err
 		}
-		err = setServiceScale(project, name, uint64(replicas))
+		err = setServiceScale(project, name, replicas)
 		if err != nil {
 			return err
 		}

+ 1 - 1
cmd/compose/create_test.go

@@ -21,7 +21,7 @@ import (
 	"fmt"
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/davecgh/go-spew/spew"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/mocks"

+ 1 - 1
cmd/compose/exec.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"context"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/compose/v2/pkg/api"

+ 1 - 1
cmd/compose/options.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"fmt"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/utils"
 )
 

+ 1 - 1
cmd/compose/options_test.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/stretchr/testify/require"
 )
 

+ 1 - 1
cmd/compose/pull.go

@@ -21,7 +21,7 @@ import (
 	"fmt"
 	"os"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/morikuni/aec"
 	"github.com/spf13/cobra"

+ 1 - 1
cmd/compose/pullOptions_test.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"gotest.tools/v3/assert"
 )
 

+ 1 - 1
cmd/compose/push.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"context"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/spf13/cobra"
 

+ 4 - 4
cmd/compose/run.go

@@ -21,12 +21,12 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/compose-spec/compose-go/v2/format"
 	xprogress "github.com/moby/buildkit/util/progress/progressui"
 	"github.com/sirupsen/logrus"
 
-	cgo "github.com/compose-spec/compose-go/cli"
-	"github.com/compose-spec/compose-go/loader"
-	"github.com/compose-spec/compose-go/types"
+	cgo "github.com/compose-spec/compose-go/v2/cli"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/cli/opts"
 	"github.com/mattn/go-shellwords"
@@ -98,7 +98,7 @@ func (options runOptions) apply(project *types.Project) error {
 	}
 
 	for _, v := range options.volumes {
-		volume, err := loader.ParseVolume(v)
+		volume, err := format.ParseVolume(v)
 		if err != nil {
 			return err
 		}

+ 5 - 5
cmd/compose/scale.go

@@ -24,7 +24,7 @@ import (
 
 	"github.com/docker/cli/cli/command"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"golang.org/x/exp/maps"
 
 	"github.com/docker/compose/v2/pkg/api"
@@ -77,11 +77,11 @@ func runScale(ctx context.Context, dockerCli command.Cli, backend api.Service, o
 			if service.Name != key {
 				continue
 			}
-			if service.Deploy == nil {
-				service.Deploy = &types.DeployConfig{}
+			value := value
+			service.Scale = &value
+			if service.Deploy != nil {
+				service.Deploy.Replicas = &value
 			}
-			scale := uint64(value)
-			service.Deploy.Replicas = &scale
 			project.Services[i] = service
 			break
 		}

+ 5 - 5
cmd/compose/up.go

@@ -25,7 +25,7 @@ import (
 
 	xprogress "github.com/moby/buildkit/util/progress/progressui"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/compose/v2/cmd/formatter"
 	"github.com/spf13/cobra"
@@ -259,7 +259,7 @@ func runUp(
 	})
 }
 
-func setServiceScale(project *types.Project, name string, replicas uint64) error {
+func setServiceScale(project *types.Project, name string, replicas int) error {
 	for i, s := range project.Services {
 		if s.Name != name {
 			continue
@@ -269,10 +269,10 @@ func setServiceScale(project *types.Project, name string, replicas uint64) error
 		if err != nil {
 			return err
 		}
-		if service.Deploy == nil {
-			service.Deploy = &types.DeployConfig{}
+		service.Scale = &replicas
+		if service.Deploy != nil {
+			service.Deploy.Replicas = &replicas
 		}
-		service.Deploy.Replicas = &replicas
 		project.Services[i] = service
 		return nil
 	}

+ 12 - 4
cmd/compose/up_test.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"gotest.tools/v3/assert"
 )
 
@@ -31,13 +31,21 @@ func TestApplyScaleOpt(t *testing.T) {
 			},
 			{
 				Name: "bar",
+				Deploy: &types.DeployConfig{
+					Mode: "test",
+				},
 			},
 		},
 	}
-	opt := createOptions{scale: []string{"foo=2"}}
-	err := opt.Apply(&p)
+	err := applyScaleOpts(&p, []string{"foo=2", "bar=3"})
 	assert.NilError(t, err)
 	foo, err := p.GetService("foo")
 	assert.NilError(t, err)
-	assert.Equal(t, *foo.Deploy.Replicas, uint64(2))
+	assert.Equal(t, *foo.Scale, 2)
+
+	bar, err := p.GetService("bar")
+	assert.NilError(t, err)
+	assert.Equal(t, *bar.Scale, 3)
+	assert.Equal(t, *bar.Deploy.Replicas, 3)
+
 }

+ 1 - 1
cmd/compose/watch.go

@@ -20,7 +20,7 @@ import (
 	"context"
 	"fmt"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/compose/v2/internal/locker"

+ 1 - 1
go.mod

@@ -6,7 +6,7 @@ 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.20.2
+	github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992
 	github.com/containerd/console v1.0.3
 	github.com/containerd/containerd v1.7.7
 	github.com/davecgh/go-spew v1.1.1

+ 2 - 2
go.sum

@@ -132,8 +132,8 @@ 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 v1.20.2 h1:u/yfZHn4EaHGdidrZycWpxXgFffjYULlTbRfJ51ykjQ=
-github.com/compose-spec/compose-go v1.20.2/go.mod h1:+MdqXV4RA7wdFsahh/Kb8U0pAJqkg7mr4PM9tFKU8RM=
+github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992 h1:0BM7GPtSRK7djjvG3h67aJYH8eRikBgxkrEG7wNtgaU=
+github.com/compose-spec/compose-go/v2 v2.0.0-20231121074112-593b77722992/go.mod h1:uAthZuC/GWStR8mxGMRaQyaOeSqA4V+MZIiAIfuBoIU=
 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.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=

+ 3 - 3
internal/sync/docker_cp.go

@@ -22,7 +22,7 @@ import (
 	"io/fs"
 	"os"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/sirupsen/logrus"
 )
@@ -63,8 +63,8 @@ func (d *DockerCopy) Sync(ctx context.Context, service types.ServiceConfig, path
 
 func (d *DockerCopy) sync(ctx context.Context, service types.ServiceConfig, pathMapping PathMapping) error {
 	scale := 1
-	if service.Deploy != nil && service.Deploy.Replicas != nil {
-		scale = int(*service.Deploy.Replicas)
+	if service.Scale != nil {
+		scale = *service.Scale
 	}
 
 	if fi, statErr := os.Stat(pathMapping.HostPath); statErr == nil {

+ 1 - 1
internal/sync/shared.go

@@ -17,7 +17,7 @@ package sync
 import (
 	"context"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 )
 
 // PathMapping contains the Compose service and modified host system path.

+ 1 - 1
internal/sync/tar.go

@@ -32,7 +32,7 @@ import (
 
 	"github.com/hashicorp/go-multierror"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	moby "github.com/docker/docker/api/types"
 	"github.com/docker/docker/pkg/archive"
 )

+ 1 - 1
internal/tracing/attributes.go

@@ -22,7 +22,7 @@ import (
 
 	"github.com/docker/compose/v2/pkg/utils"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	moby "github.com/docker/docker/api/types"
 	"go.opentelemetry.io/otel/attribute"
 	"go.opentelemetry.io/otel/trace"

+ 1 - 1
pkg/api/api.go

@@ -22,7 +22,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/utils"
 )
 

+ 1 - 1
pkg/api/api_test.go

@@ -19,7 +19,7 @@ package api
 import (
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"gotest.tools/v3/assert"
 )
 

+ 1 - 1
pkg/api/proxy.go

@@ -19,7 +19,7 @@ package api
 import (
 	"context"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 )
 
 var _ Service = &ServiceProxy{}

+ 1 - 1
pkg/compose/attach.go

@@ -23,7 +23,7 @@ import (
 	"io"
 	"strings"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/streams"
 	moby "github.com/docker/docker/api/types"
 	containerType "github.com/docker/docker/api/types/container"

+ 1 - 1
pkg/compose/build.go

@@ -26,7 +26,7 @@ import (
 
 	"github.com/moby/buildkit/util/progress/progressui"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/containerd/containerd/platforms"
 	"github.com/docker/buildx/build"
 	"github.com/docker/buildx/builder"

+ 1 - 1
pkg/compose/build_classic.go

@@ -31,7 +31,7 @@ import (
 
 	"github.com/docker/docker/api/types/registry"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli"
 	"github.com/docker/cli/cli/command/image/build"
 	dockertypes "github.com/docker/docker/api/types"

+ 17 - 7
pkg/compose/compose.go

@@ -29,7 +29,7 @@ import (
 
 	"github.com/docker/docker/api/types/volume"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/distribution/reference"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/cli/cli/config/configfile"
@@ -177,23 +177,25 @@ func (s *composeService) Config(ctx context.Context, project *types.Project, opt
 // projectFromName builds a types.Project based on actual resources with compose labels set
 func (s *composeService) projectFromName(containers Containers, projectName string, services ...string) (*types.Project, error) {
 	project := &types.Project{
-		Name: projectName,
+		Name:     projectName,
+		Services: types.Services{},
 	}
 	if len(containers) == 0 {
 		return project, fmt.Errorf("no container found for project %q: %w", projectName, api.ErrNotFound)
 	}
-	set := map[string]*types.ServiceConfig{}
+	set := map[string]types.ServiceConfig{}
 	for _, c := range containers {
 		serviceLabel := c.Labels[api.ServiceLabel]
-		_, ok := set[serviceLabel]
+		service, ok := set[serviceLabel]
 		if !ok {
-			set[serviceLabel] = &types.ServiceConfig{
+			service = types.ServiceConfig{
 				Name:   serviceLabel,
 				Image:  c.Image,
 				Labels: c.Labels,
 			}
+			set[serviceLabel] = service
 		}
-		set[serviceLabel].Scale++
+		service.Scale = increment(service.Scale)
 	}
 	for _, service := range set {
 		dependencies := service.Labels[api.DependenciesLabel]
@@ -217,7 +219,7 @@ func (s *composeService) projectFromName(containers Containers, projectName stri
 				service.DependsOn[dependency] = types.ServiceDependency{Condition: condition, Restart: restart, Required: required}
 			}
 		}
-		project.Services = append(project.Services, *service)
+		project.Services = append(project.Services, service)
 	}
 SERVICES:
 	for _, qs := range services {
@@ -236,6 +238,14 @@ SERVICES:
 	return project, nil
 }
 
+func increment(scale *int) *int {
+	i := 1
+	if scale != nil {
+		i = *scale + 1
+	}
+	return &i
+}
+
 func (s *composeService) actualVolumes(ctx context.Context, projectName string) (types.Volumes, error) {
 	opts := volume.ListOptions{
 		Filters: filters.NewArgs(projectFilter(projectName)),

+ 1 - 1
pkg/compose/containers.go

@@ -22,7 +22,7 @@ import (
 	"sort"
 	"strconv"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/utils"
 	moby "github.com/docker/docker/api/types"

+ 7 - 4
pkg/compose/convergence.go

@@ -29,7 +29,7 @@ import (
 	"go.opentelemetry.io/otel/attribute"
 	"go.opentelemetry.io/otel/trace"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/containerd/containerd/platforms"
 	"github.com/docker/compose/v2/internal/tracing"
 	moby "github.com/docker/docker/api/types"
@@ -428,7 +428,7 @@ func shouldWaitForDependency(serviceName string, dependencyConfig types.ServiceD
 			}
 		}
 		return false, err
-	} else if service.Scale == 0 {
+	} else if service.Scale != nil && *service.Scale == 0 {
 		// don't wait for the dependency which configured to have 0 containers running
 		return false, nil
 	}
@@ -457,8 +457,11 @@ func nextContainerNumber(containers []moby.Container) int {
 
 func getScale(config types.ServiceConfig) (int, error) {
 	scale := 1
-	if config.Deploy != nil && config.Deploy.Replicas != nil {
-		scale = int(*config.Deploy.Replicas)
+	if config.Scale != nil {
+		scale = *config.Scale
+	} else if config.Deploy != nil && config.Deploy.Replicas != nil {
+		// this should not be required as compose-go enforce consistency between scale anr replicas
+		scale = *config.Deploy.Replicas
 	}
 	if scale > 1 && config.ContainerName != "" {
 		return 0, fmt.Errorf(doubledContainerNameWarning,

+ 15 - 13
pkg/compose/convergence_test.go

@@ -22,7 +22,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	moby "github.com/docker/docker/api/types"
 	containerType "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/filters"
@@ -37,31 +37,33 @@ func TestContainerName(t *testing.T) {
 	s := types.ServiceConfig{
 		Name:          "testservicename",
 		ContainerName: "testcontainername",
-		Scale:         1,
+		Scale:         intPtr(1),
 		Deploy:        &types.DeployConfig{},
 	}
 	ret, err := getScale(s)
 	assert.NilError(t, err)
-	assert.Equal(t, ret, s.Scale)
+	assert.Equal(t, ret, *s.Scale)
 
-	var zero uint64 // = 0
-	s.Deploy.Replicas = &zero
+	s.Scale = intPtr(0)
 	ret, err = getScale(s)
 	assert.NilError(t, err)
-	assert.Equal(t, ret, int(*s.Deploy.Replicas))
+	assert.Equal(t, ret, *s.Scale)
 
-	var two uint64 = 2
-	s.Deploy.Replicas = &two
+	s.Scale = intPtr(2)
 	_, err = getScale(s)
 	assert.Error(t, err, fmt.Sprintf(doubledContainerNameWarning, s.Name, s.ContainerName))
 }
 
+func intPtr(i int) *int {
+	return &i
+}
+
 func TestServiceLinks(t *testing.T) {
 	const dbContainerName = "/" + testProject + "-db-1"
 	const webContainerName = "/" + testProject + "-web-1"
 	s := types.ServiceConfig{
 		Name:  "web",
-		Scale: 1,
+		Scale: intPtr(1),
 	}
 
 	containerListOptions := containerType.ListOptions{
@@ -223,8 +225,8 @@ func TestWaitDependencies(t *testing.T) {
 	cli.EXPECT().Client().Return(apiClient).AnyTimes()
 
 	t.Run("should skip dependencies with scale 0", func(t *testing.T) {
-		dbService := types.ServiceConfig{Name: "db", Scale: 0}
-		redisService := types.ServiceConfig{Name: "redis", Scale: 0}
+		dbService := types.ServiceConfig{Name: "db", Scale: intPtr(0)}
+		redisService := types.ServiceConfig{Name: "redis", Scale: intPtr(0)}
 		project := types.Project{Name: strings.ToLower(testProject), Services: types.Services{dbService, redisService}}
 		dependencies := types.DependsOnConfig{
 			"db":    {Condition: ServiceConditionRunningOrHealthy},
@@ -233,8 +235,8 @@ func TestWaitDependencies(t *testing.T) {
 		assert.NilError(t, tested.waitDependencies(context.Background(), &project, "", dependencies, nil))
 	})
 	t.Run("should skip dependencies with condition service_started", func(t *testing.T) {
-		dbService := types.ServiceConfig{Name: "db", Scale: 1}
-		redisService := types.ServiceConfig{Name: "redis", Scale: 1}
+		dbService := types.ServiceConfig{Name: "db", Scale: intPtr(1)}
+		redisService := types.ServiceConfig{Name: "redis", Scale: intPtr(1)}
 		project := types.Project{Name: strings.ToLower(testProject), Services: types.Services{dbService, redisService}}
 		dependencies := types.DependsOnConfig{
 			"db":    {Condition: types.ServiceConditionStarted, Required: true},

+ 1 - 1
pkg/compose/convert.go

@@ -20,7 +20,7 @@ import (
 	"fmt"
 	"time"
 
-	compose "github.com/compose-spec/compose-go/types"
+	compose "github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/docker/api/types/container"
 )
 

+ 6 - 6
pkg/compose/create.go

@@ -41,7 +41,7 @@ import (
 	"github.com/docker/go-units"
 	"github.com/sirupsen/logrus"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/progress"
@@ -810,7 +810,7 @@ func buildContainerConfigMounts(p types.Project, s types.ServiceConfig) ([]mount
 		}
 
 		definedConfig := p.Configs[config.Source]
-		if definedConfig.External.External {
+		if definedConfig.External {
 			return nil, fmt.Errorf("unsupported external config %s", definedConfig.Name)
 		}
 
@@ -860,7 +860,7 @@ func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount
 		}
 
 		definedSecret := p.Secrets[secret.Source]
-		if definedSecret.External.External {
+		if definedSecret.External {
 			return nil, fmt.Errorf("unsupported external secret %s", definedSecret.Name)
 		}
 
@@ -1019,7 +1019,7 @@ func buildTmpfsOptions(tmpfs *types.ServiceVolumeTmpfs) *mount.TmpfsOptions {
 }
 
 func (s *composeService) ensureNetwork(ctx context.Context, n *types.NetworkConfig) error {
-	if n.External.External {
+	if n.External {
 		return s.resolveExternalNetwork(ctx, n)
 	}
 
@@ -1206,14 +1206,14 @@ func (s *composeService) ensureVolume(ctx context.Context, volume types.VolumeCo
 		if !errdefs.IsNotFound(err) {
 			return err
 		}
-		if volume.External.External {
+		if volume.External {
 			return fmt.Errorf("external volume %q not found", volume.Name)
 		}
 		err := s.createVolume(ctx, volume)
 		return err
 	}
 
-	if volume.External.External {
+	if volume.External {
 		return nil
 	}
 

+ 1 - 1
pkg/compose/create_test.go

@@ -26,7 +26,7 @@ import (
 
 	"github.com/docker/compose/v2/pkg/api"
 
-	composetypes "github.com/compose-spec/compose-go/types"
+	composetypes "github.com/compose-spec/compose-go/v2/types"
 	moby "github.com/docker/docker/api/types"
 	mountTypes "github.com/docker/docker/api/types/mount"
 

+ 1 - 1
pkg/compose/dependencies.go

@@ -22,7 +22,7 @@ import (
 	"strings"
 	"sync"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/api"
 	"golang.org/x/sync/errgroup"
 

+ 1 - 1
pkg/compose/dependencies_test.go

@@ -23,7 +23,7 @@ import (
 	"sync"
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/utils"
 	testify "github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"

+ 3 - 3
pkg/compose/down.go

@@ -24,7 +24,7 @@ import (
 
 	"github.com/docker/compose/v2/pkg/utils"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	moby "github.com/docker/docker/api/types"
 	containerType "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/filters"
@@ -136,7 +136,7 @@ func checkSelectedServices(options api.DownOptions, project *types.Project) ([]s
 func (s *composeService) ensureVolumesDown(ctx context.Context, project *types.Project, w progress.Writer) []downOp {
 	var ops []downOp
 	for _, vol := range project.Volumes {
-		if vol.External.External {
+		if vol.External {
 			continue
 		}
 		volumeName := vol.Name
@@ -171,7 +171,7 @@ func (s *composeService) ensureImagesDown(ctx context.Context, project *types.Pr
 func (s *composeService) ensureNetworksDown(ctx context.Context, project *types.Project, w progress.Writer) []downOp {
 	var ops []downOp
 	for key, n := range project.Networks {
-		if n.External.External {
+		if n.External {
 			continue
 		}
 		// loop capture variable for op closure

+ 1 - 1
pkg/compose/down_test.go

@@ -23,7 +23,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli/streams"
 	moby "github.com/docker/docker/api/types"
 	containerType "github.com/docker/docker/api/types/container"

+ 1 - 1
pkg/compose/errors.go

@@ -20,7 +20,7 @@ import (
 	"errors"
 	"io/fs"
 
-	"github.com/compose-spec/compose-go/errdefs"
+	"github.com/compose-spec/compose-go/v2/errdefs"
 )
 
 // Error error to categorize failures and extract metrics info

+ 5 - 6
pkg/compose/hash.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"encoding/json"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/opencontainers/go-digest"
 )
 
@@ -28,12 +28,11 @@ func ServiceHash(o types.ServiceConfig) (string, error) {
 	// remove the Build config when generating the service hash
 	o.Build = nil
 	o.PullPolicy = ""
-	if o.Deploy == nil {
-		o.Deploy = &types.DeployConfig{}
+	o.Scale = nil
+	if o.Deploy != nil {
+		o.Deploy.Replicas = nil
 	}
-	o.Scale = 1
-	var one uint64 = 1
-	o.Deploy.Replicas = &one
+
 	bytes, err := json.Marshal(o)
 	if err != nil {
 		return "", err

+ 3 - 3
pkg/compose/hash_test.go

@@ -19,7 +19,7 @@ package compose
 import (
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"gotest.tools/v3/assert"
 )
 
@@ -31,9 +31,9 @@ func TestServiceHash(t *testing.T) {
 	assert.Equal(t, hash1, hash2)
 }
 
-func serviceConfig(replicas uint64) types.ServiceConfig {
+func serviceConfig(replicas int) types.ServiceConfig {
 	return types.ServiceConfig{
-		Scale: int(replicas),
+		Scale: &replicas,
 		Deploy: &types.DeployConfig{
 			Replicas: &replicas,
 		},

+ 1 - 1
pkg/compose/image_pruner.go

@@ -22,7 +22,7 @@ import (
 	"sort"
 	"sync"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/distribution/reference"
 	moby "github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"

+ 1 - 1
pkg/compose/logs_test.go

@@ -23,7 +23,7 @@ import (
 	"sync"
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	moby "github.com/docker/docker/api/types"
 	containerType "github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/api/types/filters"

+ 7 - 6
pkg/compose/publish.go

@@ -20,7 +20,7 @@ import (
 	"context"
 	"os"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/distribution/reference"
 	"github.com/docker/buildx/util/imagetools"
 	"github.com/docker/compose/v2/internal/ocipush"
@@ -122,12 +122,13 @@ func (s *composeService) generateImageDigestsOverride(ctx context.Context, proje
 	if err != nil {
 		return nil, err
 	}
-	override := types.Project{}
-	for _, service := range project.Services {
-		override.Services = append(override.Services, types.ServiceConfig{
-			Name:  service.Name,
+	override := types.Project{
+		Services: types.Services{},
+	}
+	for name, service := range project.Services {
+		override.Services[name] = types.ServiceConfig{
 			Image: service.Image,
-		})
+		}
 	}
 	return override.MarshalYAML()
 }

+ 1 - 1
pkg/compose/pull.go

@@ -25,7 +25,7 @@ import (
 	"io"
 	"strings"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/distribution/reference"
 	"github.com/docker/buildx/driver"
 	moby "github.com/docker/docker/api/types"

+ 1 - 1
pkg/compose/push.go

@@ -25,7 +25,7 @@ import (
 	"io"
 	"strings"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/distribution/reference"
 	"github.com/docker/buildx/driver"
 	moby "github.com/docker/docker/api/types"

+ 1 - 1
pkg/compose/restart.go

@@ -20,7 +20,7 @@ import (
 	"context"
 	"strings"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/progress"
 	"github.com/docker/compose/v2/pkg/utils"

+ 3 - 2
pkg/compose/run.go

@@ -23,7 +23,7 @@ import (
 	"os"
 	"os/signal"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli"
 	cmd "github.com/docker/cli/cli/command/container"
 	"github.com/docker/compose/v2/pkg/api"
@@ -73,7 +73,8 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
 	if service.ContainerName == "" {
 		service.ContainerName = fmt.Sprintf("%[1]s%[4]s%[2]s%[4]srun%[4]s%[3]s", project.Name, service.Name, stringid.TruncateID(slug), api.Separator)
 	}
-	service.Scale = 1
+	one := 1
+	service.Scale = &one
 	service.Restart = ""
 	if service.Deploy != nil {
 		service.Deploy.RestartPolicy = nil

+ 1 - 1
pkg/compose/scale.go

@@ -18,7 +18,7 @@ package compose
 import (
 	"context"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/internal/tracing"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/progress"

+ 1 - 1
pkg/compose/secrets.go

@@ -24,7 +24,7 @@ import (
 	"strconv"
 	"time"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	moby "github.com/docker/docker/api/types"
 )
 

+ 1 - 1
pkg/compose/start.go

@@ -30,7 +30,7 @@ import (
 	"github.com/docker/compose/v2/pkg/progress"
 	"github.com/docker/compose/v2/pkg/utils"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	moby "github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"golang.org/x/sync/errgroup"

+ 1 - 1
pkg/compose/up.go

@@ -23,7 +23,7 @@ import (
 	"os/signal"
 	"syscall"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/cli/cli"
 	"github.com/docker/compose/v2/internal/tracing"
 	"github.com/docker/compose/v2/pkg/api"

+ 6 - 6
pkg/compose/viz.go

@@ -21,7 +21,7 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/api"
 )
 
@@ -30,13 +30,13 @@ type vizGraph map[*types.ServiceConfig][]*types.ServiceConfig
 
 func (s *composeService) Viz(_ context.Context, project *types.Project, opts api.VizOptions) (string, error) {
 	graph := make(vizGraph)
-	for i, serviceConfig := range project.Services {
-		serviceConfigPtr := &project.Services[i]
-		graph[serviceConfigPtr] = make([]*types.ServiceConfig, 0, len(serviceConfig.DependsOn))
-		for dependencyName := range serviceConfig.DependsOn {
+	for _, service := range project.Services {
+		service := service
+		graph[&service] = make([]*types.ServiceConfig, 0, len(service.DependsOn))
+		for dependencyName := range service.DependsOn {
 			// no error should be returned since dependencyName should exist
 			dependency, _ := project.GetService(dependencyName)
-			graph[serviceConfigPtr] = append(graph[serviceConfigPtr], &dependency)
+			graph[&service] = append(graph[&service], &dependency)
 		}
 	}
 

+ 1 - 1
pkg/compose/viz_test.go

@@ -21,7 +21,7 @@ import (
 	"strconv"
 	"testing"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/golang/mock/gomock"
 	"github.com/stretchr/testify/assert"
 

+ 1 - 1
pkg/compose/watch.go

@@ -27,7 +27,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/internal/sync"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/watch"

+ 1 - 1
pkg/compose/watch_test.go

@@ -20,7 +20,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/internal/sync"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/mocks"

+ 13 - 9
pkg/e2e/scale_test.go

@@ -40,18 +40,21 @@ func TestScaleBasicCases(t *testing.T) {
 
 	t.Log("scale up one service")
 	res = c.RunDockerComposeCmd(t, "--project-directory", "fixtures/scale", "scale", "dbadmin=2")
-	checkServiceContainer(t, res.Combined(), "scale-basic-tests-dbadmin", "Started", 2)
+	out := res.Combined()
+	checkServiceContainer(t, out, "scale-basic-tests-dbadmin", "Started", 2)
 
 	t.Log("scale up 2 services")
 	res = c.RunDockerComposeCmd(t, "--project-directory", "fixtures/scale", "scale", "front=3", "back=2")
-	checkServiceContainer(t, res.Combined(), "scale-basic-tests-front", "Running", 2)
-	checkServiceContainer(t, res.Combined(), "scale-basic-tests-front", "Started", 1)
-	checkServiceContainer(t, res.Combined(), "scale-basic-tests-back", "Running", 1)
-	checkServiceContainer(t, res.Combined(), "scale-basic-tests-back", "Started", 1)
+	out = res.Combined()
+	checkServiceContainer(t, out, "scale-basic-tests-front", "Running", 2)
+	checkServiceContainer(t, out, "scale-basic-tests-front", "Started", 1)
+	checkServiceContainer(t, out, "scale-basic-tests-back", "Running", 1)
+	checkServiceContainer(t, out, "scale-basic-tests-back", "Started", 1)
 
 	t.Log("scale down one service")
 	res = c.RunDockerComposeCmd(t, "--project-directory", "fixtures/scale", "scale", "dbadmin=1")
-	checkServiceContainer(t, res.Combined(), "scale-basic-tests-dbadmin", "Running", 1)
+	out = res.Combined()
+	checkServiceContainer(t, out, "scale-basic-tests-dbadmin", "Running", 1)
 
 	t.Log("scale to 0 a service")
 	res = c.RunDockerComposeCmd(t, "--project-directory", "fixtures/scale", "scale", "dbadmin=0")
@@ -59,9 +62,10 @@ func TestScaleBasicCases(t *testing.T) {
 
 	t.Log("scale down 2 services")
 	res = c.RunDockerComposeCmd(t, "--project-directory", "fixtures/scale", "scale", "front=2", "back=1")
-	checkServiceContainer(t, res.Combined(), "scale-basic-tests-front", "Running", 2)
-	assert.Check(t, !strings.Contains(res.Combined(), "Container scale-basic-tests-front-3  Running"), res.Combined())
-	checkServiceContainer(t, res.Combined(), "scale-basic-tests-back", "Running", 1)
+	out = res.Combined()
+	checkServiceContainer(t, out, "scale-basic-tests-front", "Running", 2)
+	assert.Check(t, !strings.Contains(out, "Container scale-basic-tests-front-3  Running"), res.Combined())
+	checkServiceContainer(t, out, "scale-basic-tests-back", "Running", 1)
 }
 
 func TestScaleWithDepsCases(t *testing.T) {

+ 1 - 1
pkg/mocks/mock_docker_compose_api.go

@@ -8,7 +8,7 @@ import (
 	context "context"
 	reflect "reflect"
 
-	types "github.com/compose-spec/compose-go/types"
+	types "github.com/compose-spec/compose-go/v2/types"
 	api "github.com/docker/compose/v2/pkg/api"
 	gomock "github.com/golang/mock/gomock"
 )

+ 3 - 3
pkg/remote/git.go

@@ -25,9 +25,9 @@ import (
 	"regexp"
 	"strconv"
 
-	"github.com/compose-spec/compose-go/cli"
-	"github.com/compose-spec/compose-go/loader"
-	"github.com/compose-spec/compose-go/types"
+	"github.com/compose-spec/compose-go/v2/cli"
+	"github.com/compose-spec/compose-go/v2/loader"
+	"github.com/compose-spec/compose-go/v2/types"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/moby/buildkit/util/gitutil"
 )

+ 1 - 1
pkg/remote/oci.go

@@ -25,7 +25,7 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/compose-spec/compose-go/loader"
+	"github.com/compose-spec/compose-go/v2/loader"
 	"github.com/distribution/reference"
 	"github.com/docker/buildx/store/storeutil"
 	"github.com/docker/buildx/util/imagetools"