buildx: Building images for multi-arch with --load parameter fails

While trying to build images for multi-architecture (AMD64 and ARM64), I tried to load them into the Docker daemon with the --load parameter but I got an error:

➜ docker buildx build --platform linux/arm64,linux/amd64 --load  -t carlosedp/test:v1  .
[+] Building 1.3s (24/24) FINISHED
 => [internal] load .dockerignore                                                                                                                                                        0.0s
 => => transferring context: 2B                                                                                                                                                          0.0s
 => [internal] load build definition from Dockerfile                                                                                                                                     0.0s
 => => transferring dockerfile: 115B                                                                                                                                                     0.0s
 => [linux/amd64 internal] load metadata for docker.io/library/alpine:latest                                                                                                             0.8s
 => [linux/amd64 internal] load metadata for docker.io/library/golang:1.12-alpine                                                                                                        1.0s
 => [linux/arm64 internal] load metadata for docker.io/library/golang:1.12-alpine                                                                                                        1.2s
 => [linux/arm64 internal] load metadata for docker.io/library/alpine:latest                                                                                                             1.2s
 => [linux/amd64 builder 1/5] FROM docker.io/library/golang:1.12-alpine@sha256:1a5f8b6db670a7776ce5beeb69054a7cf7047a5d83176d39b94665a54cfb9756                                          0.0s
 => => resolve docker.io/library/golang:1.12-alpine@sha256:1a5f8b6db670a7776ce5beeb69054a7cf7047a5d83176d39b94665a54cfb9756                                                              0.0s
 => [linux/amd64 stage-1 1/4] FROM docker.io/library/alpine@sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913                                                      0.0s
 => => resolve docker.io/library/alpine@sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913                                                                          0.0s
 => [internal] load build context                                                                                                                                                        0.0s
 => => transferring context: 232B                                                                                                                                                        0.0s
 => CACHED [linux/amd64 stage-1 2/4] RUN apk add --no-cache file &&     rm -rf /var/cache/apk/*                                                                                          0.0s
 => CACHED [linux/amd64 builder 2/5] WORKDIR /go/src/app                                                                                                                                 0.0s
 => CACHED [linux/amd64 builder 3/5] ADD . /go/src/app/                                                                                                                                  0.0s
 => CACHED [linux/amd64 builder 4/5] RUN CGO_ENABLED=0 go build -o main .                                                                                                                0.0s
 => CACHED [linux/amd64 builder 5/5] RUN mv /go/src/app/main /                                                                                                                           0.0s
 => CACHED [linux/amd64 stage-1 3/4] COPY --from=builder /main /main                                                                                                                     0.0s
 => [linux/arm64 builder 1/5] FROM docker.io/library/golang:1.12-alpine@sha256:1a5f8b6db670a7776ce5beeb69054a7cf7047a5d83176d39b94665a54cfb9756                                          0.0s
 => => resolve docker.io/library/golang:1.12-alpine@sha256:1a5f8b6db670a7776ce5beeb69054a7cf7047a5d83176d39b94665a54cfb9756                                                              0.0s
 => [linux/arm64 stage-1 1/4] FROM docker.io/library/alpine@sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913                                                      0.0s
 => => resolve docker.io/library/alpine@sha256:28ef97b8686a0b5399129e9b763d5b7e5ff03576aa5580d6f4182a49c5fe1913                                                                          0.0s
 => CACHED [linux/arm64 stage-1 2/4] RUN apk add --no-cache file &&     rm -rf /var/cache/apk/*                                                                                          0.0s
 => CACHED [linux/arm64 builder 2/5] WORKDIR /go/src/app                                                                                                                                 0.0s
 => CACHED [linux/arm64 builder 3/5] ADD . /go/src/app/                                                                                                                                  0.0s
 => CACHED [linux/arm64 builder 4/5] RUN CGO_ENABLED=0 go build -o main .                                                                                                                0.0s
 => CACHED [linux/arm64 builder 5/5] RUN mv /go/src/app/main /                                                                                                                           0.0s
 => CACHED [linux/arm64 stage-1 3/4] COPY --from=builder /main /main                                                                                                                     0.0s
 => ERROR exporting to oci image format                                                                                                                                                  0.0s
------
 > exporting to oci image format:
------
failed to solve: rpc error: code = Unknown desc = docker exporter does not currently support exporting manifest lists

I understand that the daemon can’t see the manifest lists but I believe there should be a way to tag the images with some variable, like:

docker buildx build --platform linux/arm64,linux/amd64 --load -t carlosedp/test:v1-$ARCH .

To have both images loaded into the daemon and ignoring the manifest list in this case.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 51
  • Comments: 34 (4 by maintainers)

Commits related to this issue

Most upvoted comments

you should use --push on multi-platform , use --load for single platform。

@git-developer The current limitation is combination of --load and multiple values to --platform. Eg. --platform linux/arm64 --load works fine.

https://github.com/docker/buildx/issues/59#issuecomment-488902807

“limitation is temporary” … in 2019.

Hi, this issue is 5 months old and the linked issue (moby/moby#38738) is still in Draft. Any news?

I’m hitting this as well… any updates?

This is still a problem in 2023, if this feature is complete already, why isn’t it merged and available?

You can do this:

# build both images
docker buildx build --platform linux/arm64,linux/amd64 .
# load just one platform
docker buildx build --load --platform linux/amd64 -t my-image-tag .
# optionally load another platform with a different tag
docker buildx build --load --platform linux/arm64 -t my-image-tag:arm64 .
# push both platforms as one image manifest list
docker buildx build --push --platform linux/arm64,linux/amd64 -t docker.palantir.build/publish:tag .

Unfortunately the docker daemon does not support tags pointing at a manifest list, rather than a manifest. Which is why if you do:

docker pull --platform linux/arm64 ubuntu:20.04
docker pull --platform linux/amd64 ubuntu:20.04

It will retag the local ubuntu:20.04 image each time rather than have ubuntu:20.04 point to a manifest list.

Ok lol so this doesn’t work yet after almost three years. Can we ever get it working?

There are very good reasons as multiple people in this thread have pointed out and at the time we didn’t even have Apple Silicon released. Which would make this even more useful.

Heya folks 👋

Though I’d x-post my comment from #1220 since it seems relevant:

This is actually in progress, see https://github.com/docker/roadmap/issues/371. This is not a buildx/buildkit limitation so we can’t do much until that’s completed, since it’s an issue that docker currently can’t store multi-arch images in the content store - but as mentioned, can confirm this work is now in-progress. TL;DR - the migration to the containerd store will allow loading multi-arch images, so --load will load multi-arch images properly.

[…] trying to build multi-arch image and loading to local docker instance for testing purposes.

Depending on the use case it may be sufficient when tests run on the runner’s platform only. If so, this issue can be avoided by omitting the platform parameter on load. Example:

  • Build: docker buildx build --platform linux/arm64,linux/amd64 -t foo/bar:latest .
  • Test: docker buildx build --load -t foo/bar:latest .

Couldn’t it work in a way in which there’s --platform specified with multiple platforms and --load would only load the one the local docker arch supports? This would allow to build and load in one command which is very handy

The pipeline in the project I’m working on runs tests before pushing. Do I have to build the image once for the test and then a second time for production?

Is there any workaround to run a multiarch container before pushing it to a repo?

How would I tag an image with a version and latest?

@Filius-Patris You’re options are:

  • run tests are part of the build
  • build single arch image, test with docker run, then build multi-arch image. Cache from the first build will be reused.
  • use a local registry

IMHIO, this shouldn’t be closed @tonistiigi - this is not “fixed” by a “mention” in the docs. There’s a real need, shown by this long running issue. 3 years…

The pipeline in the project I’m working on runs tests before pushing. Do I have to build the image once for the test and then a second time for production?

Is there any workaround to run a multiarch container before pushing it to a repo?

Same problem for me, i have to build with --push on each gitlab-ci stages… using --platform linux/arm/v7,linux/amd64

I also landed here and I’m not sure what the options are, on a practical level it seems like a hack to support “docker build” commands and docker buildx to get around the issue.

Would it be possible to put in some logic on the buildx side to have --load only export the image if the platform matches? Print a warning, fail hard, anything else if none of the platforms specified match OS?

This was closed because of https://github.com/moby/moby/pull/38738. But now that issue has been closed as development has stopped (https://github.com/moby/moby/pull/38738#issuecomment-1005279865). Can we reopen this one?

It would be cool if it could “load” multi-arch images, and use only the correct one. So that if you say, re-tag and push, you could do it across architectures.

A lot of code does build/tag/push in separate places.

Hi, I’ve the same issue as the original message, trying to build multi-arch image and loading to local docker instance for testing purposes.

I want to build and execute some local tests before pushing the image to the repository. Previously for this purpose, I had used standard build command (tagging the architecture) with qemu.

Build runs fine, but at the end…

 => ERROR exporting to oci image format                                                                                                  0.0s
------
 > exporting to oci image format:
------
failed to solve: rpc error: code = Unknown desc = docker exporter does not currently support exporting manifest lists
Build failed
make: *** [build] Error 3

Here’s my environment:

docker version

Client: Docker Engine - Community
 Version:           19.03.5
 API version:       1.40
 Go version:        go1.12.12
 Git commit:        633a0ea
 Built:             Wed Nov 13 07:22:34 2019
 OS/Arch:           darwin/amd64
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          19.03.5
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.12
  Git commit:       633a0ea
  Built:            Wed Nov 13 07:29:19 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

docker buildx version

github.com/docker/buildx v0.3.1-tp-docker 6db68d029599c6710a32aa7adcba8e5a344795a7

@Filius-Patris You’re options are:

  • run tests are part of the build
  • build single arch image, test with docker run, then build multi-arch image. Cache from the first build will be reused.
  • use a local registry

I would like to know more about the “use a local registry” option, please.

Hi All,

does anyone know the solution to the above problem? I can push images to the registry without any issue but when I try to load them on the docker desktop I face the below issue, which is same as above.

error: docker exporter does not currently support exporting manifest lists

I think because it can’t be fixed right? It actually makes sense in that if you build a multi arch image, you can’t --load it as local docker doesn’t support having multi-arch images (when you do a docker pull it’ll pull a single arch based on your system). So best case --load would have to just load the architecture for your current host.

This problem just happened to me. Why this issue is closed if issue still exist?

@skhamkar-tibco i don’t know of a way. Currently you can’t use —load with cross-platform builds.

The limitation is temporary as daemon should get support for loading multi-arch with https://github.com/moby/moby/pull/38738 so I’m a bit hesitant to add a custom implementation for it atm.

@sakoht docker buildx build --platform linux/arm64,linux/amd64 -t "${image_name}:${GOOS}-${GOARCH}" --push . The above commands work perfectly, I can see images in the registry. But I want to inspect them locally and then push them to the registry. But when I execute the below command it gives the issue mentioned on this thread. docker buildx build --platform linux/arm64,linux/amd64 -t "${image_name}:${GOOS}-${GOARCH}" --load .

But again when I provide a single platform, It works perfectly and I can see the image in Docker Desktop. Like this - docker buildx build --platform linux/arm64 -t "${image_name}:${GOOS}-${GOARCH}" --load .