diff --git a/cmd/compose/tracing.go b/cmd/compose/tracing.go index f8ae7c29..99ff58d8 100644 --- a/cmd/compose/tracing.go +++ b/cmd/compose/tracing.go @@ -20,8 +20,8 @@ import ( "github.com/moby/buildkit/util/tracing/detect" "go.opentelemetry.io/otel" - _ "github.com/moby/buildkit/util/tracing/detect/delegated" //nolint:revive - _ "github.com/moby/buildkit/util/tracing/env" //nolint:revive + _ "github.com/moby/buildkit/util/tracing/detect/delegated" //nolint:blank-imports + _ "github.com/moby/buildkit/util/tracing/env" //nolint:blank-imports ) func init() { diff --git a/pkg/compose/build.go b/pkg/compose/build.go index db8df618..6282e7a8 100644 --- a/pkg/compose/build.go +++ b/pkg/compose/build.go @@ -173,7 +173,11 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri if len(opt.Platforms) > 1 { opt.Exports = []bclient.ExportEntry{{ Type: "docker", + Attrs: map[string]string{ + "load": "true", + }, }} + opt.Platforms = []specs.Platform{} } opts[imageName] = opt continue diff --git a/pkg/compose/build_buildkit.go b/pkg/compose/build_buildkit.go index 4e8812f5..fb3981ab 100644 --- a/pkg/compose/build_buildkit.go +++ b/pkg/compose/build_buildkit.go @@ -37,9 +37,9 @@ import ( "github.com/docker/buildx/build" "github.com/docker/buildx/driver" - _ "github.com/docker/buildx/driver/docker" //nolint:revive - _ "github.com/docker/buildx/driver/docker-container" //nolint:revive - _ "github.com/docker/buildx/driver/kubernetes" //nolint:revive + _ "github.com/docker/buildx/driver/docker" //nolint:blank-imports + _ "github.com/docker/buildx/driver/docker-container" //nolint:blank-imports + _ "github.com/docker/buildx/driver/kubernetes" //nolint:blank-imports xprogress "github.com/docker/buildx/util/progress" ) @@ -56,8 +56,10 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, opts map[string]bu defer cancel() w := xprogress.NewPrinter(progressCtx, s.stdout(), os.Stdout, mode) - // We rely on buildx "docker" builder integrated in docker engine, so don't need a DockerAPI here - response, err := build.Build(ctx, dis, opts, nil, filepath.Dir(s.configFile().Filename), w) + // Get the DockerAPI if a "docker" export is defined (ie: up and run command), otherwise get nil and let use the default buildx builder + API := getDockerAPI(s.dockerCli, opts) + + response, err := build.Build(ctx, dis, opts, API, filepath.Dir(s.configFile().Filename), w) errW := w.Wait() if err == nil { err = errW @@ -252,3 +254,29 @@ func configFromContext(endpointName string, s ctxstore.Reader) (clientcmd.Client } return ctxkube.ConfigFromContext(endpointName, s) } + +type internalAPI struct { + dockerCli command.Cli +} + +func (a *internalAPI) DockerAPI(name string) (dockerclient.APIClient, error) { + if name == "" { + name = a.dockerCli.CurrentContext() + } + return clientForEndpoint(a.dockerCli, name) +} + +func dockerAPI(dockerCli command.Cli) *internalAPI { + return &internalAPI{dockerCli: dockerCli} +} + +func getDockerAPI(cli command.Cli, opts map[string]build.Options) *internalAPI { + for _, opt := range opts { + for _, export := range opt.Exports { + if export.Type == "docker" { + return dockerAPI(cli) + } + } + } + return nil +} diff --git a/pkg/e2e/build_test.go b/pkg/e2e/build_test.go index 30fb9a4a..7aacf2b5 100644 --- a/pkg/e2e/build_test.go +++ b/pkg/e2e/build_test.go @@ -258,6 +258,7 @@ func TestBuildPlatformsWithCorrectBuildxConfig(t *testing.T) { assert.NilError(t, result.Error) t.Cleanup(func() { + c.RunDockerComposeCmd(t, "--project-directory", "fixtures/build-test/platforms", "down") _ = c.RunDockerCmd(t, "buildx", "rm", "-f", "build-platform") _ = c.RunDockerCmd(t, "rm", "-f", "registry") }) @@ -279,6 +280,12 @@ func TestBuildPlatformsWithCorrectBuildxConfig(t *testing.T) { res.Assert(t, icmd.Expected{Out: `"architecture": "arm64",`}) }) + + t.Run("multi-arch up --build", func(t *testing.T) { + res := c.RunDockerComposeCmdNoCheck(t, "--project-directory", "fixtures/build-test/platforms", "up", "--build") + assert.NilError(t, res.Error, res.Stderr()) + res.Assert(t, icmd.Expected{Out: "platforms-platforms-1 exited with code 0"}) + }) } func TestBuildPlatformsStandardErrors(t *testing.T) { diff --git a/pkg/e2e/fixtures/build-test/platforms/Dockerfile b/pkg/e2e/fixtures/build-test/platforms/Dockerfile index 8f59df16..643926d8 100644 --- a/pkg/e2e/fixtures/build-test/platforms/Dockerfile +++ b/pkg/e2e/fixtures/build-test/platforms/Dockerfile @@ -12,6 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -FROM alpine +FROM --platform=$BUILDPLATFORM golang:alpine AS build -RUN echo "SUCCESS" +ARG TARGETPLATFORM +ARG BUILDPLATFORM +RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log + +FROM alpine +COPY --from=build /log /log diff --git a/pkg/e2e/fixtures/build-test/platforms/compose.yaml b/pkg/e2e/fixtures/build-test/platforms/compose.yaml index 2e16fbe3..e8ba350a 100644 --- a/pkg/e2e/fixtures/build-test/platforms/compose.yaml +++ b/pkg/e2e/fixtures/build-test/platforms/compose.yaml @@ -1,7 +1,6 @@ services: platforms: image: localhost:5001/build-test-platform:test - platform: linux/amd64 build: context: . platforms: