From 002c7d098631a868c8725d1b72c012eff93b339d Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Sun, 27 Feb 2022 10:25:18 +0100 Subject: [PATCH 1/3] build: return remote digest for pushed image with docker driver Signed-off-by: CrazyMax --- build/build.go | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/build/build.go b/build/build.go index b6da2fa5d16d..c968088921f9 100644 --- a/build/build.go +++ b/build/build.go @@ -833,7 +833,7 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do respMu.Lock() resp[k] = &client.SolveResponse{ ExporterResponse: map[string]string{ - "containerimage.digest": desc.Digest.String(), + exptypes.ExporterImageDigestKey: desc.Digest.String(), }, } respMu.Unlock() @@ -918,7 +918,6 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do if err != nil { return err } - res[i] = rr d := drivers[dp.driverIndex].Driver if d.IsMobyDriver() { @@ -930,17 +929,26 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do return errors.Errorf("tag is needed when pushing to registry") } pw := progress.ResetTime(pw) - for _, name := range strings.Split(pushNames, ",") { + pushList := strings.Split(pushNames, ",") + for _, name := range pushList { if err := progress.Wrap(fmt.Sprintf("pushing %s with docker", name), pw.Write, func(l progress.SubLogger) error { return pushWithMoby(ctx, d, name, l) }); err != nil { return err } } + remoteDigest, errp := remoteDigestWithMoby(ctx, d, pushList[0]) + if errp == nil && remoteDigest != "" { + rr.ExporterResponse[exptypes.ExporterImageDigestKey] = remoteDigest + } else if errp != nil { + return err + } } } } } + + res[i] = rr return nil }) @@ -1038,9 +1046,33 @@ func pushWithMoby(ctx context.Context, d driver.Driver, name string, l progress. parsedError = jm.Error } } + return nil } +func remoteDigestWithMoby(ctx context.Context, d driver.Driver, name string) (string, error) { + api := d.Config().DockerAPI + if api == nil { + return "", errors.Errorf("invalid empty Docker API reference") // should never happen + } + creds, err := imagetools.RegistryAuthForRef(name, d.Config().Auth) + if err != nil { + return "", err + } + image, _, err := api.ImageInspectWithRaw(ctx, name) + if err != nil { + return "", err + } + if len(image.RepoDigests) == 0 { + return "", nil + } + remoteImage, err := api.DistributionInspect(ctx, name, creds) + if err != nil { + return "", err + } + return remoteImage.Descriptor.Digest.String(), nil +} + func createTempDockerfile(r io.Reader) (string, error) { dir, err := ioutil.TempDir("", "dockerfile") if err != nil { From 443fcc6355b9ee6526669586e94554b1d61a6e4e Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Sun, 27 Feb 2022 21:18:14 +0100 Subject: [PATCH 2/3] build: return imageID when loading without docker driver Signed-off-by: CrazyMax --- build/build.go | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/build/build.go b/build/build.go index c968088921f9..8703f2f10cb9 100644 --- a/build/build.go +++ b/build/build.go @@ -762,7 +762,7 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do resp[k] = res[0] respMu.Unlock() if len(res) == 1 { - digest := res[0].ExporterResponse["containerimage.digest"] + digest := res[0].ExporterResponse[exptypes.ExporterImageDigestKey] if opt.ImageIDFile != "" { return ioutil.WriteFile(opt.ImageIDFile, []byte(digest), 0644) } @@ -774,7 +774,7 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do descs := make([]specs.Descriptor, 0, len(res)) for _, r := range res { - s, ok := r.ExporterResponse["containerimage.digest"] + s, ok := r.ExporterResponse[exptypes.ExporterImageDigestKey] if ok { descs = append(descs, specs.Descriptor{ Digest: digest.Digest(s), @@ -920,8 +920,9 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do } d := drivers[dp.driverIndex].Driver - if d.IsMobyDriver() { - for _, e := range so.Exports { + + for _, e := range so.Exports { + if d.IsMobyDriver() { if e.Type == "moby" && e.Attrs["push"] != "" { if ok, _ := strconv.ParseBool(e.Attrs["push"]); ok { pushNames = e.Attrs["name"] @@ -937,14 +938,22 @@ func Build(ctx context.Context, drivers []DriverInfo, opt map[string]Options, do return err } } - remoteDigest, errp := remoteDigestWithMoby(ctx, d, pushList[0]) - if errp == nil && remoteDigest != "" { + remoteDigest, err := remoteDigestWithMoby(ctx, d, pushList[0]) + if err == nil && remoteDigest != "" { rr.ExporterResponse[exptypes.ExporterImageDigestKey] = remoteDigest - } else if errp != nil { + } else if err != nil { return err } } } + } else if names, ok := e.Attrs["name"]; ok && e.Type == "docker" { + nameList := strings.Split(names, ",") + imageID, err := dockerImageID(ctx, d, nameList[0]) + if err == nil && imageID != "" { + rr.ExporterResponse[exptypes.ExporterImageDigestKey] = imageID + } else if err != nil { + return err + } } } @@ -1073,6 +1082,18 @@ func remoteDigestWithMoby(ctx context.Context, d driver.Driver, name string) (st return remoteImage.Descriptor.Digest.String(), nil } +func dockerImageID(ctx context.Context, d driver.Driver, name string) (string, error) { + api := d.Config().DockerAPI + if api == nil { + return "", errors.Errorf("invalid empty Docker API reference") // should never happen + } + image, _, err := api.ImageInspectWithRaw(ctx, name) + if err != nil { + return "", err + } + return image.ID, nil +} + func createTempDockerfile(r io.Reader) (string, error) { dir, err := ioutil.TempDir("", "dockerfile") if err != nil { From d84512ea9fb5272b305c3ecf9ef3f602ab2b2176 Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Sun, 27 Feb 2022 22:11:26 +0100 Subject: [PATCH 3/3] docs: additional info for iidfile flag Signed-off-by: CrazyMax --- commands/build.go | 2 +- docs/reference/buildx_build.md | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/commands/build.go b/commands/build.go index f63214b40f2c..67af18623a19 100644 --- a/commands/build.go +++ b/commands/build.go @@ -357,7 +357,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command { flags.StringVarP(&options.dockerfileName, "file", "f", "", `Name of the Dockerfile (default: "PATH/Dockerfile")`) flags.SetAnnotation("file", annotation.ExternalURL, []string{"https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f"}) - flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to the file") + flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID or digest to the file") flags.StringArrayVar(&options.labels, "label", []string{}, "Set metadata for an image") diff --git a/docs/reference/buildx_build.md b/docs/reference/buildx_build.md index 2a8339d3f255..a816bf50e0b9 100644 --- a/docs/reference/buildx_build.md +++ b/docs/reference/buildx_build.md @@ -24,7 +24,7 @@ Start a build | [`--cache-to`](#cache-to) | `stringArray` | | Cache export destinations (e.g., `user/app:cache`, `type=local,dest=path/to/dir`) | | [`--cgroup-parent`](https://docs.docker.com/engine/reference/commandline/build/#use-a-custom-parent-cgroup---cgroup-parent) | `string` | | Optional parent cgroup for the container | | [`-f`](https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f), [`--file`](https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) | -| `--iidfile` | `string` | | Write the image ID to the file | +| [`--iidfile`](#iidfile) | `string` | | Write the image ID or digest to the file | | `--label` | `stringArray` | | Set metadata for an image | | [`--load`](#load) | | | Shorthand for `--output=type=docker` | | [`--metadata-file`](#metadata-file) | `string` | | Write build result metadata to the file | @@ -210,6 +210,16 @@ $ docker buildx build --cache-to=type=gha . More info about cache exporters and available attributes: https://github.com/moby/buildkit#export-cache +### Write the image ID or digest to the file (--iidfile) + +Output the image ID or digest depending on the driver and output being used to +the specified file: + +* `docker` driver : writes the image ID. +* `docker` driver with `--push`: writes the image digest. +* `docker-container` driver with `--load`: writes the image ID. +* `docker-container` driver with `--push`: writes the image digest. + ### Load the single-platform build result to `docker images` (--load) Shorthand for [`--output=type=docker`](#docker). Will automatically load the