Skip to content

Commit 1506bbc

Browse files
committed
builder-next: Add ImageNamedByBuildkit callback
When image is built with buildkit with containerd integration the image service has no way of knowing that the image was tagged because buildkit creates the image directly in containerd image store. Add a callback that is called by the exporter wrapper. Signed-off-by: Paweł Gronowski <[email protected]>
1 parent bce76d4 commit 1506bbc

7 files changed

Lines changed: 95 additions & 61 deletions

File tree

api/server/backend/build/backend.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,9 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
8888
}
8989
}
9090

91-
if !useBuildKit {
92-
stdout := config.ProgressWriter.StdoutFormatter
93-
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
94-
}
9591
if imageID != "" && !useBuildKit {
92+
stdout := config.ProgressWriter.StdoutFormatter
93+
_, _ = fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
9694
err = tagImages(ctx, b.imageComponent, config.ProgressWriter.StdoutFormatter, image.ID(imageID), tags)
9795
}
9896
return imageID, err

builder/builder-next/builder.go

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -77,24 +77,24 @@ var cacheFields = map[string]bool{
7777

7878
// Opt is option struct required for creating the builder
7979
type Opt struct {
80-
SessionManager *session.Manager
81-
Root string
82-
EngineID string
83-
Dist images.DistributionServices
84-
ImageTagger mobyexporter.ImageTagger
85-
NetworkController *libnetwork.Controller
86-
DefaultCgroupParent string
87-
RegistryHosts docker.RegistryHosts
88-
BuilderConfig config.BuilderConfig
89-
Rootless bool
90-
IdentityMapping idtools.IdentityMapping
91-
DNSConfig config.DNSConfig
92-
ApparmorProfile string
93-
UseSnapshotter bool
94-
Snapshotter string
95-
ContainerdAddress string
96-
ContainerdNamespace string
97-
ImageExportedCallback exporter.ImageExportedByBuildkit
80+
SessionManager *session.Manager
81+
Root string
82+
EngineID string
83+
Dist images.DistributionServices
84+
ImageTagger mobyexporter.ImageTagger
85+
NetworkController *libnetwork.Controller
86+
DefaultCgroupParent string
87+
RegistryHosts docker.RegistryHosts
88+
BuilderConfig config.BuilderConfig
89+
Rootless bool
90+
IdentityMapping idtools.IdentityMapping
91+
DNSConfig config.DNSConfig
92+
ApparmorProfile string
93+
UseSnapshotter bool
94+
Snapshotter string
95+
ContainerdAddress string
96+
ContainerdNamespace string
97+
Callbacks exporter.BuildkitCallbacks
9898
}
9999

100100
// Builder can build using BuildKit backend

builder/builder-next/controller.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt
138138
}
139139
wo.Executor = exec
140140

141-
w, err := mobyworker.NewContainerdWorker(ctx, wo, opt.ImageExportedCallback)
141+
w, err := mobyworker.NewContainerdWorker(ctx, wo, opt.Callbacks)
142142
if err != nil {
143143
return nil, err
144144
}
@@ -321,7 +321,8 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt
321321
Differ: differ,
322322
ImageTagger: opt.ImageTagger,
323323
LeaseManager: lm,
324-
ImageExportedCallback: opt.ImageExportedCallback,
324+
ImageExportedCallback: opt.Callbacks.Exported,
325+
// Callbacks.Named is not used here because the tag operation is handled directly by the image service.
325326
})
326327
if err != nil {
327328
return nil, err

builder/builder-next/exporter/mobyexporter/export.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"github.com/containerd/containerd/leases"
1111
"github.com/containerd/log"
1212
distref "github.com/distribution/reference"
13-
builderexporter "github.com/docker/docker/builder/builder-next/exporter"
1413
"github.com/docker/docker/image"
1514
"github.com/docker/docker/layer"
1615
"github.com/moby/buildkit/exporter"
@@ -38,7 +37,7 @@ type Opt struct {
3837
ImageTagger ImageTagger
3938
ContentStore content.Store
4039
LeaseManager leases.Manager
41-
ImageExportedCallback builderexporter.ImageExportedByBuildkit
40+
ImageExportedCallback func(ctx context.Context, id string, desc ocispec.Descriptor)
4241
}
4342

4443
type imageExporter struct {

builder/builder-next/exporter/wrapper.go

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,38 @@ import (
44
"context"
55
"strings"
66

7+
"github.com/containerd/log"
8+
"github.com/distribution/reference"
79
"github.com/docker/docker/builder/builder-next/exporter/overrides"
810
"github.com/moby/buildkit/exporter"
911
"github.com/moby/buildkit/exporter/containerimage/exptypes"
1012

1113
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
1214
)
1315

14-
type ImageExportedByBuildkit = func(ctx context.Context, id string, desc ocispec.Descriptor)
16+
type BuildkitCallbacks struct {
17+
// Exported is a Called when an image is exported by buildkit.
18+
Exported func(ctx context.Context, id string, desc ocispec.Descriptor)
19+
20+
// Named is a callback that is called when an image is created in the
21+
// containerd image store by buildkit.
22+
Named func(ctx context.Context, ref reference.NamedTagged, desc ocispec.Descriptor)
23+
}
1524

1625
// Wraps the containerimage exporter's Resolve method to apply moby-specific
1726
// overrides to the exporter attributes.
1827
type imageExporterMobyWrapper struct {
19-
exp exporter.Exporter
20-
callback ImageExportedByBuildkit
28+
exp exporter.Exporter
29+
callbacks BuildkitCallbacks
2130
}
2231

2332
// NewWrapper returns an exporter wrapper that applies moby specific attributes
2433
// and hooks the export process.
25-
func NewWrapper(exp exporter.Exporter, callback ImageExportedByBuildkit) (exporter.Exporter, error) {
26-
return &imageExporterMobyWrapper{exp: exp, callback: callback}, nil
34+
func NewWrapper(exp exporter.Exporter, callbacks BuildkitCallbacks) (exporter.Exporter, error) {
35+
return &imageExporterMobyWrapper{
36+
exp: exp,
37+
callbacks: callbacks,
38+
}, nil
2739
}
2840

2941
// Resolve applies moby specific attributes to the request.
@@ -46,12 +58,15 @@ func (e *imageExporterMobyWrapper) Resolve(ctx context.Context, id int, exporter
4658
return nil, err
4759
}
4860

49-
return &imageExporterInstanceWrapper{ExporterInstance: inst, callback: e.callback}, nil
61+
return &imageExporterInstanceWrapper{
62+
ExporterInstance: inst,
63+
callbacks: e.callbacks,
64+
}, nil
5065
}
5166

5267
type imageExporterInstanceWrapper struct {
5368
exporter.ExporterInstance
54-
callback ImageExportedByBuildkit
69+
callbacks BuildkitCallbacks
5570
}
5671

5772
func (i *imageExporterInstanceWrapper) Export(ctx context.Context, src *exporter.Source, inlineCache exptypes.InlineCache, sessionID string) (map[string]string, exporter.DescriptorReference, error) {
@@ -62,8 +77,26 @@ func (i *imageExporterInstanceWrapper) Export(ctx context.Context, src *exporter
6277

6378
desc := ref.Descriptor()
6479
imageID := out[exptypes.ExporterImageDigestKey]
65-
if i.callback != nil {
66-
i.callback(ctx, imageID, desc)
80+
if i.callbacks.Exported != nil {
81+
i.callbacks.Exported(ctx, imageID, desc)
82+
}
83+
84+
if i.callbacks.Named != nil {
85+
for _, name := range strings.Split(out[string(exptypes.OptKeyName)], ",") {
86+
ref, err := reference.ParseNormalizedNamed(name)
87+
if err != nil {
88+
// Shouldn't happen, but log if it does and continue.
89+
log.G(ctx).WithFields(log.Fields{
90+
"name": name,
91+
"error": err,
92+
}).Warn("image named with invalid reference produced by buildkit")
93+
continue
94+
}
95+
96+
namedTagged := reference.TagNameOnly(ref).(reference.NamedTagged)
97+
i.callbacks.Named(ctx, namedTagged, desc)
98+
}
6799
}
100+
68101
return out, ref, nil
69102
}

builder/builder-next/worker/containerdworker.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,37 @@ package worker
33
import (
44
"context"
55

6-
mobyexporter "github.com/docker/docker/builder/builder-next/exporter"
6+
"github.com/docker/docker/builder/builder-next/exporter"
77
"github.com/moby/buildkit/client"
8-
"github.com/moby/buildkit/exporter"
8+
bkexporter "github.com/moby/buildkit/exporter"
99
"github.com/moby/buildkit/session"
1010
"github.com/moby/buildkit/worker/base"
1111
)
1212

1313
// ContainerdWorker is a local worker instance with dedicated snapshotter, cache, and so on.
1414
type ContainerdWorker struct {
1515
*base.Worker
16-
callback mobyexporter.ImageExportedByBuildkit
16+
callbacks exporter.BuildkitCallbacks
1717
}
1818

1919
// NewContainerdWorker instantiates a local worker.
20-
func NewContainerdWorker(ctx context.Context, wo base.WorkerOpt, callback mobyexporter.ImageExportedByBuildkit) (*ContainerdWorker, error) {
20+
func NewContainerdWorker(ctx context.Context, wo base.WorkerOpt, callbacks exporter.BuildkitCallbacks) (*ContainerdWorker, error) {
2121
bw, err := base.NewWorker(ctx, wo)
2222
if err != nil {
2323
return nil, err
2424
}
25-
return &ContainerdWorker{Worker: bw, callback: callback}, nil
25+
return &ContainerdWorker{Worker: bw, callbacks: callbacks}, nil
2626
}
2727

2828
// Exporter returns exporter by name
29-
func (w *ContainerdWorker) Exporter(name string, sm *session.Manager) (exporter.Exporter, error) {
29+
func (w *ContainerdWorker) Exporter(name string, sm *session.Manager) (bkexporter.Exporter, error) {
3030
switch name {
31-
case mobyexporter.Moby:
31+
case exporter.Moby:
3232
exp, err := w.Worker.Exporter(client.ExporterImage, sm)
3333
if err != nil {
3434
return nil, err
3535
}
36-
return mobyexporter.NewWrapper(exp, w.callback)
36+
return exporter.NewWrapper(exp, w.callbacks)
3737
default:
3838
return w.Worker.Exporter(name, sm)
3939
}

cmd/dockerd/daemon.go

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
systemrouter "github.com/docker/docker/api/server/router/system"
3636
"github.com/docker/docker/api/server/router/volume"
3737
buildkit "github.com/docker/docker/builder/builder-next"
38+
"github.com/docker/docker/builder/builder-next/exporter"
3839
"github.com/docker/docker/builder/dockerfile"
3940
"github.com/docker/docker/cmd/dockerd/debug"
4041
"github.com/docker/docker/cmd/dockerd/trap"
@@ -430,24 +431,26 @@ func newRouterOptions(ctx context.Context, config *config.Config, d *daemon.Daem
430431
cgroupParent := newCgroupParent(config)
431432

432433
bk, err := buildkit.New(ctx, buildkit.Opt{
433-
SessionManager: sm,
434-
Root: filepath.Join(config.Root, "buildkit"),
435-
EngineID: d.ID(),
436-
Dist: d.DistributionServices(),
437-
ImageTagger: d.ImageService(),
438-
NetworkController: d.NetworkController(),
439-
DefaultCgroupParent: cgroupParent,
440-
RegistryHosts: d.RegistryHosts,
441-
BuilderConfig: config.Builder,
442-
Rootless: daemon.Rootless(config),
443-
IdentityMapping: d.IdentityMapping(),
444-
DNSConfig: config.DNSConfig,
445-
ApparmorProfile: daemon.DefaultApparmorProfile(),
446-
UseSnapshotter: d.UsesSnapshotter(),
447-
Snapshotter: d.ImageService().StorageDriver(),
448-
ContainerdAddress: config.ContainerdAddr,
449-
ContainerdNamespace: config.ContainerdNamespace,
450-
ImageExportedCallback: d.ImageExportedByBuildkit,
434+
SessionManager: sm,
435+
Root: filepath.Join(config.Root, "buildkit"),
436+
EngineID: d.ID(),
437+
Dist: d.DistributionServices(),
438+
ImageTagger: d.ImageService(),
439+
NetworkController: d.NetworkController(),
440+
DefaultCgroupParent: cgroupParent,
441+
RegistryHosts: d.RegistryHosts,
442+
BuilderConfig: config.Builder,
443+
Rootless: daemon.Rootless(config),
444+
IdentityMapping: d.IdentityMapping(),
445+
DNSConfig: config.DNSConfig,
446+
ApparmorProfile: daemon.DefaultApparmorProfile(),
447+
UseSnapshotter: d.UsesSnapshotter(),
448+
Snapshotter: d.ImageService().StorageDriver(),
449+
ContainerdAddress: config.ContainerdAddr,
450+
ContainerdNamespace: config.ContainerdNamespace,
451+
Callbacks: exporter.BuildkitCallbacks{
452+
Exported: d.ImageExportedByBuildkit,
453+
},
451454
})
452455
if err != nil {
453456
return routerOptions{}, err

0 commit comments

Comments
 (0)