diff --git a/build/build.go b/build/build.go
index b6da2fa5d16d..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),
@@ -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,11 +918,11 @@ 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() {
- 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"]
@@ -930,17 +930,34 @@ 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, err := remoteDigestWithMoby(ctx, d, pushList[0])
+ if err == nil && remoteDigest != "" {
+ rr.ExporterResponse[exptypes.ExporterImageDigestKey] = remoteDigest
+ } 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
+ }
}
}
+
+ res[i] = rr
return nil
})
@@ -1038,9 +1055,45 @@ 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 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 {
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