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 22, 2025
1 parent 52578c0 commit 5e03fce
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 41 deletions.
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.20250122084341-25e1083beabb
github.com/containerd/containerd v1.7.24
github.com/containerd/platforms v0.2.1
github.com/davecgh/go-spew v1.1.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,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.20250122084341-25e1083beabb h1:TDtkmu7WlsYNwapWsB6fV7pFB7rCCDLFbZQykZ+lO5A=
github.com/compose-spec/compose-go/v2 v2.4.8-0.20250122084341-25e1083beabb/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc=
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
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=
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
89 changes: 55 additions & 34 deletions pkg/compose/build_bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,27 @@ type bakeGroup struct {
}

type bakeTarget struct {
Context string `json:"context,omitempty"`
Dockerfile string `json:"dockerfile,omitempty"`
Args map[string]string `json:"args,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
Tags []string `json:"tags,omitempty"`
CacheFrom []string `json:"cache-from,omitempty"`
CacheTo []string `json:"cache-to,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"`
Context string `json:"context,omitempty"`
Contexts map[string]string `json:"contexts,omitempty"`
Dockerfile string `json:"dockerfile,omitempty"`
DockerfileInline string `json:"dockerfile-inline,omitempty"`
Args map[string]string `json:"args,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
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"`
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"`
}

type bakeMetadata map[string]buildStatus
Expand All @@ -115,11 +123,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 All @@ -137,7 +140,7 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
}
var group bakeGroup

for _, service := range serviceToBeBuild {
for name, service := range serviceToBeBuild {
if service.Build == nil {
continue
}
Expand All @@ -153,23 +156,29 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project

image := api.GetImageNameOrDefault(service, project.Name)

cfg.Targets[image] = bakeTarget{
Context: build.Context,
Dockerfile: dockerFilePath(build.Context, build.Dockerfile),
Args: args,
Labels: build.Labels,
Tags: append(build.Tags, image),

CacheFrom: build.CacheFrom,
cfg.Targets[name] = bakeTarget{
Context: build.Context,
Contexts: additionalContexts(build.AdditionalContexts),
Dockerfile: dockerFilePath(build.Context, build.Dockerfile),
DockerfileInline: build.DockerfileInline,
Args: args,
Labels: build.Labels,
Tags: append(build.Tags, image),
CacheFrom: build.CacheFrom,
// CacheTo: TODO
Platforms: build.Platforms,
Target: build.Target,
Secrets: toBakeSecrets(project, build.Secrets),
SSH: toBakeSSH(build.SSH),
Pull: options.Pull,
NoCache: options.NoCache,
Target: build.Target,
Secrets: toBakeSecrets(project, build.Secrets),
SSH: toBakeSSH(build.SSH),
Platforms: build.Platforms,
Pull: options.Pull,
NoCache: options.NoCache,
NetworkMode: build.Network,
ShmSize: build.ShmSize,
// Ulimits: TODO
// Call: TODO
// Entitlements: TODO
}
group.Targets = append(group.Targets, image)
group.Targets = append(group.Targets, name)
}

cfg.Groups["default"] = group
Expand Down Expand Up @@ -250,6 +259,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 @@ -258,6 +268,17 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
return results, nil
}

func additionalContexts(contexts types.Mapping) map[string]string {
ac := map[string]string{}
for k, c := range contexts {
if target, found := strings.CutPrefix(c, types.ServicePrefix); found {
c = "target:" + target
}
ac[k] = c
}
return ac
}

func toBakeSSH(ssh types.SSHConfig) []string {
var s []string
for _, key := range ssh {
Expand Down
18 changes: 17 additions & 1 deletion 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/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/compose.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", 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 5e03fce

Please sign in to comment.