diff --git a/build/build.go b/build/build.go index 9c18dbba..0414b350 100644 --- a/build/build.go +++ b/build/build.go @@ -525,7 +525,6 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[ } } } - node := dp.Node().Driver if node.IsMobyDriver() { for _, e := range so.Exports { @@ -561,6 +560,14 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opts map[ } } } + // if prefer-image-digest is set in the solver options, remove the image + // config digest from the exporter's response + for _, e := range so.Exports { + if e.Attrs["prefer-image-digest"] == "true" { + delete(rr.ExporterResponse, exptypes.ExporterImageConfigDigestKey) + break + } + } return nil }) } diff --git a/build/opt.go b/build/opt.go index af4986e0..74fcdb38 100644 --- a/build/opt.go +++ b/build/opt.go @@ -237,6 +237,11 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt *O opt.Exports[i].Output = func(_ map[string]string) (io.WriteCloser, error) { return w, nil } + // if docker is using the containerd snapshotter, prefer to export the image digest + // (rather than the image config digest). See https://github.com/moby/moby/issues/45458. + if features[dockerutil.OCIImporter] { + opt.Exports[i].Attrs["prefer-image-digest"] = "true" + } } } else if !nodeDriver.Features(ctx)[driver.DockerExporter] { return nil, nil, notSupported(driver.DockerExporter, nodeDriver, "https://docs.docker.com/go/build-exporters/") diff --git a/tests/build.go b/tests/build.go index 09a75dc4..1e40c290 100644 --- a/tests/build.go +++ b/tests/build.go @@ -399,18 +399,25 @@ func testImageIDOutput(t *testing.T, sb integration.Sandbox) { require.Equal(t, dgst.String(), strings.TrimSpace(stdout.String())) + // read the md.json file dt, err = os.ReadFile(filepath.Join(targetDir, "md.json")) require.NoError(t, err) type mdT struct { + Digest string `json:"containerimage.digest"` ConfigDigest string `json:"containerimage.config.digest"` } + var md mdT err = json.Unmarshal(dt, &md) require.NoError(t, err) require.NotEmpty(t, md.ConfigDigest) - require.Equal(t, dgst, digest.Digest(md.ConfigDigest)) + require.NotEmpty(t, md.Digest) + + // verify the image ID output is correct + // XXX: improve this by checking that it's one of the two expected digests depending on the scenario. + require.Contains(t, []digest.Digest{digest.Digest(md.ConfigDigest), digest.Digest(md.Digest)}, dgst) } func testBuildMobyFromLocalImage(t *testing.T, sb integration.Sandbox) {