Why does docker buildx --load reject a multi-platform build, and what do you use instead?
answer
- Two flags, two different destinations
- Ask where the result is being written
- The local store keys one image per tag
- A registry is built to hold several architectures
- imagetools inspect tells you what landed
basics
~20 sThe --load flag copies the build result into the local Docker image store, which holds one architecture per tag, so a two-platform result has nowhere to go. Push it to a registry with --push instead, or load one platform at a time.
solid answer
~40 s`docker buildx build --platform linux/amd64,linux/arm64` produces one result covering two architectures, and `--load` is shorthand for the docker exporter, which writes into the engine's classic local image store. That store keys one image per tag with a single architecture, so the export is rejected. There is also an earlier failure: the default builder (the one built into the engine) refuses a multi-platform build outright and tells you to switch builders or turn on the containerd image store. In practice you either `--push` to a registry, which is the natural home for a multi-architecture tag, or `--output type=oci,dest=out.tar` for a file, or narrow to one platform (`--platform linux/arm64 --load`) when you just want to run it locally. Confirm what actually landed with `docker buildx imagetools inspect <tag>`.
code
bash · 6 linesdocker buildx build \
--platform linux/amd64,linux/arm64 \
-t registry.example.com/ingest-batch:2.7 \
--push .
docker buildx imagetools inspect registry.example.com/ingest-batch:2.7go deeper
Remember the shape of the error rather than the internals: --load puts an image on your machine and your machine wants one architecture, so a two-platform build has to go to a registry with --push.
Be ready to explain that --load and --push are exporters, that the classic image store records a single Os/Architecture per tag, and that the default engine-embedded builder refuses multi-platform builds before the export stage is even reached.
Show how you structure a pipeline around the limitation: single-platform --load for tests, a final multi-platform --push for release, and an imagetools inspect check so a silently single-arch tag never reaches production.
Own the platform decision: whether to enable the containerd image store fleet-wide so developers can load multi-platform images locally, and what that changes for tooling, disk usage and the support burden across mixed developer hardware.
## What `--load` and `--push` really are `docker buildx build` runs the build inside a *builder*, and then an **exporter** decides where the finished result goes. The flags most people use are shorthands for exporters: - `--load` is `--output type=docker` — encode the result in the Docker image format and hand it to the local engine's image store, so that `docker images` and `docker run` can see it. - `--push` is `--output type=image,push=true` — write the result to a registry under the tag you passed with `-t`. Nothing about the build itself changes between the two. What changes is the *destination*, and the destinations do not have the same capabilities. ## Two different failures, with two different messages When someone runs `docker buildx build --platform linux/amd64,linux/arm64 -t ingest-batch:2.7 --load .` for the first time, they usually hit one of two errors, and it matters which. **1. The builder refuses.** The default builder is the one embedded in the Docker engine itself. It can only build for the engine's own platform, so a two-platform request fails before any instruction runs, with a message along the lines of *multi-platform build is not supported for the docker driver* and a hint to switch to another builder or enable the containerd image store. The fix is to create a builder that supports it (`docker buildx create --use`) — the builder machinery itself belongs to a separate discussion; what matters here is that the default one is single-platform. **2. The export refuses.** With a multi-platform-capable builder, the build succeeds — you will see both architectures' steps run — and then the *export* fails. The engine's classic image store records exactly one image per tag, with one `Architecture` and one `Os` field. A result that covers two architectures has no representation there, so the docker exporter rejects it. So the mental model is: the build can produce two architectures, the local store can only remember one. ## What to do instead - **`--push`.** A registry is designed to hold one tag that resolves to several architectures, and a client picks the matching one at pull time. This is why nearly every real multi-platform pipeline is `buildx build --platform ... --push`, never `--load`. - **`--output type=oci,dest=image.tar`.** An OCI layout tarball can hold both architectures. It is useful for air-gapped transfer or for handing the artefact to another tool, but you cannot then `docker load` that multi-platform tarball into the classic store — the same limitation applies. - **Narrow to one platform.** `docker buildx build --platform linux/arm64 -t ingest-batch:2.7 --load .` works fine. This is the everyday local-development case, and it is worth stressing that `--platform` with a *single* value plus `--load` is perfectly legal; only two or more values break. - **Turn on the containerd image store.** Newer Docker Engine and Docker Desktop can back the local image store with containerd, which *can* hold a multi-platform image locally; there, `--load` of a multi-platform build works. That is an engine-level setting, not a build flag, and you cannot assume a colleague's machine has it on. - **Run a local registry.** Pushing to a registry running on localhost and pulling back is a common CI trick when you want a multi-platform artefact without touching a shared registry. ## Verifying what you produced After a `--push`, do not assume. `docker buildx imagetools inspect registry.example.com/ingest-batch:2.7` prints the platforms the tag actually offers; if you only see `linux/amd64`, the `--platform` flag never took effect (a very common mistake is putting it after the context argument, or reusing a shell alias that drops it). `docker image inspect` is the wrong tool for this — it only ever describes the single local image, so it will happily report `arm64` and tell you nothing about what is in the registry. ## Why this shapes CI pipelines Because `--load` is single-platform, most pipelines split the work: build and `--load` one platform to run unit or smoke tests on the runner, then a final `--push` with both platforms for release. The alternative — push first, then pull the image on a runner of each architecture and test it there — costs a registry round trip but tests each architecture natively, which is the only way to catch behaviour that emulation hides.
- After a --push, how do you confirm the tag really carries both architectures?Run `docker buildx imagetools inspect <tag>`; it prints a platform line for each architecture the tag resolves to. `docker image inspect` cannot answer this — it describes only the one image sitting in your local store, so it will report whichever architecture you happen to have pulled.
- Your CI runner is amd64 but must smoke-test the arm64 image it just built. What are your options?Either build and `--load` only `linux/arm64` and run it under emulation on that runner, which requires binfmt handlers registered on the host and is slow and not fully representative, or `--push` the multi-platform tag and pull it on a native arm64 runner. The second costs a registry round trip but is the only way to test the architecture honestly.
- Does `docker save` give you a way around the --load limitation?No. `docker save` exports what is already in the local image store, so it inherits the same single-architecture constraint. If you need a file that holds both architectures, export it straight from the build with `--output type=oci,dest=out.tar`.
A registry is a shelf that can hold several editions of the same book under one title; the classic local image store is a single slot that fits exactly one edition.
saying these in an interview costs you the question
- Thinking --push and --load are interchangeable destinations
- Assuming the default builder can build multi-platform
- Believing the classic local store keeps one image per architecture
- Claiming docker save can export a multi-platform result
- Concluding multi-platform needs a separate tag per architecture
- Verifying a pushed multi-arch tag with docker image inspect