|
|
@@ -22,6 +22,7 @@ import (
|
|
|
"fmt"
|
|
|
"os"
|
|
|
"path/filepath"
|
|
|
+ "sync"
|
|
|
|
|
|
"github.com/compose-spec/compose-go/types"
|
|
|
"github.com/containerd/containerd/platforms"
|
|
|
@@ -33,6 +34,10 @@ import (
|
|
|
xprogress "github.com/docker/buildx/util/progress"
|
|
|
"github.com/docker/cli/cli/command"
|
|
|
cliopts "github.com/docker/cli/opts"
|
|
|
+ "github.com/docker/compose/v2/internal/tracing"
|
|
|
+ "github.com/docker/compose/v2/pkg/api"
|
|
|
+ "github.com/docker/compose/v2/pkg/progress"
|
|
|
+ "github.com/docker/compose/v2/pkg/utils"
|
|
|
"github.com/docker/docker/builder/remotecontext/urlutil"
|
|
|
"github.com/docker/go-units"
|
|
|
bclient "github.com/moby/buildkit/client"
|
|
|
@@ -44,11 +49,6 @@ import (
|
|
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
|
|
- "github.com/docker/compose/v2/internal/tracing"
|
|
|
- "github.com/docker/compose/v2/pkg/api"
|
|
|
- "github.com/docker/compose/v2/pkg/progress"
|
|
|
- "github.com/docker/compose/v2/pkg/utils"
|
|
|
-
|
|
|
// required to get default driver registered
|
|
|
_ "github.com/docker/buildx/driver/docker"
|
|
|
)
|
|
|
@@ -64,6 +64,11 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
|
|
|
}, s.stdinfo(), "Building")
|
|
|
}
|
|
|
|
|
|
+type serviceToBuild struct {
|
|
|
+ idx int
|
|
|
+ service types.ServiceConfig
|
|
|
+}
|
|
|
+
|
|
|
//nolint:gocyclo
|
|
|
func (s *composeService) build(ctx context.Context, project *types.Project, options api.BuildOptions, localImages map[string]string) (map[string]string, error) {
|
|
|
buildkitEnabled, err := s.dockerCli.BuildKitEnabled()
|
|
|
@@ -71,6 +76,36 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
+ imageIDs := map[string]string{}
|
|
|
+ serviceToBeBuild := map[string]serviceToBuild{}
|
|
|
+ mapServiceMutx := sync.Mutex{}
|
|
|
+ err = InDependencyOrder(ctx, project, func(ctx context.Context, name string) error {
|
|
|
+ if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ service, idx := getServiceIndex(project, name)
|
|
|
+
|
|
|
+ if service.Build == nil {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ image := api.GetImageNameOrDefault(service, project.Name)
|
|
|
+ _, localImagePresent := localImages[image]
|
|
|
+ if localImagePresent && service.PullPolicy != types.PullPolicyBuild {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ mapServiceMutx.Lock()
|
|
|
+ serviceToBeBuild[name] = serviceToBuild{idx: idx, service: service}
|
|
|
+ mapServiceMutx.Unlock()
|
|
|
+ return nil
|
|
|
+ }, func(traversal *graphTraversal) {
|
|
|
+ traversal.maxConcurrency = s.maxConcurrency
|
|
|
+ })
|
|
|
+
|
|
|
+ if err != nil || len(serviceToBeBuild) == 0 {
|
|
|
+ return imageIDs, err
|
|
|
+ }
|
|
|
+
|
|
|
// Initialize buildkit nodes
|
|
|
var (
|
|
|
b *builder.Builder
|
|
|
@@ -114,17 +149,12 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|
|
if len(options.Services) > 0 && !utils.Contains(options.Services, name) {
|
|
|
return nil
|
|
|
}
|
|
|
- service, idx := getServiceIndex(project, name)
|
|
|
-
|
|
|
- if service.Build == nil {
|
|
|
- return nil
|
|
|
- }
|
|
|
-
|
|
|
- image := api.GetImageNameOrDefault(service, project.Name)
|
|
|
- _, localImagePresent := localImages[image]
|
|
|
- if localImagePresent && service.PullPolicy != types.PullPolicyBuild {
|
|
|
+ serviceToBuild, ok := serviceToBeBuild[name]
|
|
|
+ if !ok {
|
|
|
return nil
|
|
|
}
|
|
|
+ service := serviceToBuild.service
|
|
|
+ idx := serviceToBuild.idx
|
|
|
|
|
|
if !buildkitEnabled {
|
|
|
id, err := s.doBuildClassic(ctx, project, service, options)
|
|
|
@@ -170,7 +200,6 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
- imageIDs := map[string]string{}
|
|
|
for i, imageDigest := range builtDigests {
|
|
|
if imageDigest != "" {
|
|
|
imageRef := api.GetImageNameOrDefault(project.Services[i], project.Name)
|