Skip to content

Commit

Permalink
support additional_context reference to another service
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <[email protected]>
  • Loading branch information
ndeloof committed Jan 31, 2025
1 parent 4db5fcd commit aec31d9
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 35 deletions.
21 changes: 10 additions & 11 deletions cmd/compose/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,16 @@ func (opts buildOptions) toAPIBuildOptions(services []string) (api.BuildOptions,
uiMode = "rawjson"
}
return api.BuildOptions{
Pull: opts.pull,
Push: opts.push,
Progress: uiMode,
Args: types.NewMappingWithEquals(opts.args),
NoCache: opts.noCache,
Quiet: opts.quiet,
Services: services,
Deps: opts.deps,
SSHs: SSHKeys,
Builder: builderName,
Compatibility: opts.Compatibility,
Pull: opts.pull,
Push: opts.push,
Progress: uiMode,
Args: types.NewMappingWithEquals(opts.args),
NoCache: opts.noCache,
Quiet: opts.quiet,
Services: services,
Deps: opts.deps,
SSHs: SSHKeys,
Builder: builderName,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/Microsoft/go-winio v0.6.2
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/buger/goterm v1.0.4
github.com/compose-spec/compose-go/v2 v2.4.7
github.com/compose-spec/compose-go/v2 v2.4.8-0.20250130174723-77ab539e4f3f
github.com/containerd/containerd/v2 v2.0.2
github.com/containerd/platforms v1.0.0-rc.1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
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/v2 v2.4.7 h1:WNpz5bIbKG+G+w9pfu72B1ZXr+Og9jez8TMEo8ecXPk=
github.com/compose-spec/compose-go/v2 v2.4.7/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
github.com/compose-spec/compose-go/v2 v2.4.8-0.20250130174723-77ab539e4f3f h1:turCjSVHj+0P+G6kuRsJfhhYzp1ULfTv7GVzv1dgIHQ=
github.com/compose-spec/compose-go/v2 v2.4.8-0.20250130174723-77ab539e4f3f/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
Expand Down
2 changes: 0 additions & 2 deletions pkg/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,6 @@ type BuildOptions struct {
Memory int64
// Builder name passed in the command line
Builder string
// Compatibility let compose run with best backward compatibility
Compatibility bool
}

// Apply mutates project according to build options
Expand Down
34 changes: 33 additions & 1 deletion pkg/compose/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"os"
"strings"

"github.com/compose-spec/compose-go/v2/types"
"github.com/containerd/platforms"
Expand Down Expand Up @@ -71,7 +72,33 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
if options.Deps {
policy = types.IncludeDependencies
}
err := project.ForEachService(options.Services, func(serviceName string, service *types.ServiceConfig) error {

serviceDeps := false
project, err := project.WithServicesTransform(func(serviceName string, service types.ServiceConfig) (types.ServiceConfig, error) {
if service.Build != nil {
for _, c := range service.Build.AdditionalContexts {
if t, found := strings.CutPrefix(c, types.ServicePrefix); found {
serviceDeps = true
if service.DependsOn == nil {
service.DependsOn = map[string]types.ServiceDependency{}
}
service.DependsOn[t] = types.ServiceDependency{
Condition: "build", // non-canonical, but will force dependency graph ordering
}
}
}
}
return service, nil
})
if err != nil {
return imageIDs, err
}

if serviceDeps {
logrus.Infof(`additional_context with "service:"" is better supported when delegating build go bake. Set COMPOSE_BAKE=true`)
}

err = project.ForEachService(options.Services, func(serviceName string, service *types.ServiceConfig) error {
if service.Build == nil {
return nil
}
Expand Down Expand Up @@ -536,6 +563,11 @@ func getImageBuildLabels(project *types.Project, service types.ServiceConfig) ty
func toBuildContexts(additionalContexts types.Mapping) map[string]build.NamedContext {
namedContexts := map[string]build.NamedContext{}
for name, contextPath := range additionalContexts {
if _, found := strings.CutPrefix(contextPath, types.ServicePrefix); found {
// image we depend on has been build previously, as we run in dependency order.
// this assumes use of docker engine builder, so that build can access local images
continue
}
namedContexts[name] = build.NamedContext{Path: contextPath}
}
return namedContexts
Expand Down
25 changes: 11 additions & 14 deletions pkg/compose/build_bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,17 @@ type bakeTarget struct {
Tags []string `json:"tags,omitempty"`
CacheFrom []string `json:"cache-from,omitempty"`
CacheTo []string `json:"cache-to,omitempty"`
Target string `json:"target,omitempty"`
Secrets []string `json:"secret,omitempty"`
SSH []string `json:"ssh,omitempty"`
Platforms []string `json:"platforms,omitempty"`
Target string `json:"target,omitempty"`
Pull bool `json:"pull,omitempty"`
NoCache bool `json:"no-cache,omitempty"`
NetworkMode string `json:"network,omitempty"`
NoCacheFilter []string `json:"no-cache-filter,omitempty"`
ShmSize types.UnitBytes `json:"shm-size,omitempty"`
Ulimits []string `json:"ulimits,omitempty"`
Call string `json:"call,omitempty"`
Entitlements []string `json:"entitlements,omitempty"`
Outputs []string `json:"output,omitempty"`
}
Expand All @@ -124,11 +127,6 @@ type buildStatus struct {
}

func (s *composeService) doBuildBake(ctx context.Context, project *types.Project, serviceToBeBuild types.Services, options api.BuildOptions) (map[string]string, error) { //nolint:gocyclo
cw := progress.ContextWriter(ctx)
for name := range serviceToBeBuild {
cw.Event(progress.BuildingEvent(name))
}

eg := errgroup.Group{}
ch := make(chan *client.SolveStatus)
display, err := progressui.NewDisplay(os.Stdout, progressui.DisplayMode(options.Progress))
Expand Down Expand Up @@ -191,7 +189,7 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project

cfg.Targets[serviceName] = bakeTarget{
Context: build.Context,
Contexts: additionalContexts(build.AdditionalContexts, service.DependsOn, options.Compatibility),
Contexts: additionalContexts(build.AdditionalContexts),
Dockerfile: dockerFilePath(build.Context, build.Dockerfile),
DockerfileInline: build.DockerfileInline,
Args: args,
Expand Down Expand Up @@ -221,7 +219,7 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
return nil, err
}

logrus.Debugf("bake config:\n%s", string(b))
logrus.Debugf("bake build config:\n%s", string(b))

metadata, err := os.CreateTemp(os.TempDir(), "compose")
if err != nil {
Expand Down Expand Up @@ -320,6 +318,7 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
return nil, err
}

cw := progress.ContextWriter(ctx)
results := map[string]string{}
for name, m := range md {
results[name] = m.Digest
Expand All @@ -328,14 +327,12 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
return results, nil
}

func additionalContexts(contexts types.Mapping, dependencies types.DependsOnConfig, compatibility bool) map[string]string {
func additionalContexts(contexts types.Mapping) map[string]string {
ac := map[string]string{}
if compatibility {
for name := range dependencies {
ac[name] = "target:" + name
}
}
for k, v := range contexts {
if target, found := strings.CutPrefix(v, types.ServicePrefix); found {
v = "target:" + target
}
ac[k] = v
}
return ac
Expand Down
20 changes: 18 additions & 2 deletions pkg/e2e/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,18 +271,34 @@ func TestBuildImageDependencies(t *testing.T) {
t.Run("ClassicBuilder", func(t *testing.T) {
cli := NewCLI(t, WithEnv(
"DOCKER_BUILDKIT=0",
"COMPOSE_FILE=./fixtures/build-dependencies/compose.yaml",
"COMPOSE_FILE=./fixtures/build-dependencies/classic.yaml",
))
doTest(t, cli)
})

t.Run("BuildKit by dependency order", func(t *testing.T) {
cli := NewCLI(t, WithEnv(
"DOCKER_BUILDKIT=1",
"COMPOSE_FILE=./fixtures/build-dependencies/classic.yaml",
))
doTest(t, cli)
})

t.Run("BuildKit", func(t *testing.T) {
t.Run("BuildKit by additional contexts", func(t *testing.T) {
cli := NewCLI(t, WithEnv(
"DOCKER_BUILDKIT=1",
"COMPOSE_FILE=./fixtures/build-dependencies/compose.yaml",
))
doTest(t, cli)
})

t.Run("Bake by additional contexts", func(t *testing.T) {
cli := NewCLI(t, WithEnv(
"DOCKER_BUILDKIT=1", "COMPOSE_BAKE=1",
"COMPOSE_FILE=./fixtures/build-dependencies/compose.yaml",
))
doTest(t, cli)
})
}

func TestBuildPlatformsWithCorrectBuildxConfig(t *testing.T) {
Expand Down
14 changes: 14 additions & 0 deletions pkg/e2e/fixtures/build-dependencies/classic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
services:
base:
image: base
init: true
build:
context: .
dockerfile: base.dockerfile
service:
init: true
depends_on:
- base
build:
context: .
dockerfile: service.dockerfile
4 changes: 2 additions & 2 deletions pkg/e2e/fixtures/build-dependencies/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ services:
dockerfile: base.dockerfile
service:
init: true
depends_on:
- base
build:
context: .
additional_contexts:
base: "service:base"
dockerfile: service.dockerfile

0 comments on commit aec31d9

Please sign in to comment.