diff --git a/pkg/compose/build.go b/pkg/compose/build.go index eeb2dba2e6b..689a6cd8444 100644 --- a/pkg/compose/build.go +++ b/pkg/compose/build.go @@ -205,7 +205,7 @@ func (s *composeService) doBuild(ctx context.Context, project *types.Project, op return nil, nil } if buildkitEnabled, err := s.dockerCli.BuildKitEnabled(); err != nil || !buildkitEnabled { - return s.doBuildClassic(ctx, opts) + return s.doBuildClassic(ctx, project, opts) } return s.doBuildBuildkit(ctx, project, opts, mode) } diff --git a/pkg/compose/build_classic.go b/pkg/compose/build_classic.go index 6b578dd7e90..302d55fa2eb 100644 --- a/pkg/compose/build_classic.go +++ b/pkg/compose/build_classic.go @@ -27,6 +27,7 @@ import ( "runtime" "strings" + "github.com/compose-spec/compose-go/types" buildx "github.com/docker/buildx/build" "github.com/docker/cli/cli/command/image/build" dockertypes "github.com/docker/docker/api/types" @@ -41,15 +42,24 @@ import ( "github.com/pkg/errors" ) -func (s *composeService) doBuildClassic(ctx context.Context, opts map[string]buildx.Options) (map[string]string, error) { +func (s *composeService) doBuildClassic(ctx context.Context, project *types.Project, opts map[string]buildx.Options) (map[string]string, error) { var nameDigests = make(map[string]string) var errs error - for name, o := range opts { + err := project.WithServices(nil, func(service types.ServiceConfig) error { + imageName := getImageName(service, project.Name) + o, ok := opts[imageName] + if !ok { + return nil + } digest, err := s.doBuildClassicSimpleImage(ctx, o) if err != nil { errs = multierror.Append(errs, err).ErrorOrNil() } - nameDigests[name] = digest + nameDigests[imageName] = digest + return nil + }) + if err != nil { + return nil, err } return nameDigests, errs diff --git a/pkg/e2e/compose_build_test.go b/pkg/e2e/build_test.go similarity index 87% rename from pkg/e2e/compose_build_test.go rename to pkg/e2e/build_test.go index 76a27f0321a..c7ea531bd30 100644 --- a/pkg/e2e/compose_build_test.go +++ b/pkg/e2e/build_test.go @@ -201,3 +201,40 @@ func TestBuildTags(t *testing.T) { res.Assert(t, icmd.Expected{Out: expectedOutput}) }) } + +func TestBuildImageDependencies(t *testing.T) { + doTest := func(t *testing.T, cli *CLI) { + resetState := func() { + cli.RunDockerComposeCmd(t, "down", "--rmi=all", "-t=0") + } + resetState() + t.Cleanup(resetState) + + // the image should NOT exist now + res := cli.RunDockerOrExitError(t, "image", "inspect", "build-dependencies_service") + res.Assert(t, icmd.Expected{ + ExitCode: 1, + Err: "Error: No such image: build-dependencies_service", + }) + + res = cli.RunDockerComposeCmd(t, "build") + t.Log(res.Combined()) + + res = cli.RunDockerCmd(t, + "image", "inspect", "--format={{ index .RepoTags 0 }}", + "build-dependencies_service") + res.Assert(t, icmd.Expected{Out: "build-dependencies_service:latest"}) + } + + t.Run("ClassicBuilder", func(t *testing.T) { + cli := NewParallelCLI(t, WithEnv( + "DOCKER_BUILDKIT=0", + "COMPOSE_FILE=./fixtures/build-dependencies/compose.yaml", + )) + doTest(t, cli) + }) + + t.Run("BuildKit", func(t *testing.T) { + t.Skip("See https://github.com/docker/compose/issues/9232") + }) +} diff --git a/pkg/e2e/fixtures/build-dependencies/base.dockerfile b/pkg/e2e/fixtures/build-dependencies/base.dockerfile new file mode 100644 index 00000000000..9dce0b74f41 --- /dev/null +++ b/pkg/e2e/fixtures/build-dependencies/base.dockerfile @@ -0,0 +1,19 @@ +# 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. + +FROM alpine + +COPY hello.txt /hello.txt + +CMD [ "/bin/true" ] diff --git a/pkg/e2e/fixtures/build-dependencies/compose.yaml b/pkg/e2e/fixtures/build-dependencies/compose.yaml new file mode 100644 index 00000000000..7de1960b4e9 --- /dev/null +++ b/pkg/e2e/fixtures/build-dependencies/compose.yaml @@ -0,0 +1,12 @@ +services: + base: + image: base + build: + context: . + dockerfile: base.dockerfile + service: + depends_on: + - base + build: + context: . + dockerfile: service.dockerfile diff --git a/pkg/e2e/fixtures/build-dependencies/hello.txt b/pkg/e2e/fixtures/build-dependencies/hello.txt new file mode 100644 index 00000000000..810e7ba64ac --- /dev/null +++ b/pkg/e2e/fixtures/build-dependencies/hello.txt @@ -0,0 +1 @@ +this file was copied from base -> service diff --git a/pkg/e2e/fixtures/build-dependencies/service.dockerfile b/pkg/e2e/fixtures/build-dependencies/service.dockerfile new file mode 100644 index 00000000000..95abc433d73 --- /dev/null +++ b/pkg/e2e/fixtures/build-dependencies/service.dockerfile @@ -0,0 +1,19 @@ +# 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. + +FROM alpine + +COPY --from=base /hello.txt /hello.txt + +CMD [ "cat", "/hello.txt" ]