Docker from Basics to Production · Production-Ready Images
Multi-Platform Images (amd64 and arm64)
Why an image built on an Apple Silicon laptop fails on an x86 server, and how multi-platform builds fix it.
What you'll build
You'll inspect which platforms popular images support, see what platform a local image was built for, and learn the docker buildx build --platform workflow that publishes one tag for both amd64 and arm64.
The idea
Container images contain native binaries, so they are built for a platform (OS and CPU architecture). ARM servers (AWS Graviton, Azure Cobalt, Google Axion) and Apple Silicon laptops are common, so mismatches happen:
- A single-platform image built on an arm64 laptop fails on an amd64 server with
exec format error. - A multi-platform image is an index (manifest list) pointing to one image per platform; the runtime pulls the right one automatically.
docker buildx build --platform linux/amd64,linux/arm64 -t registry.example.com/api:1.4.2 --push .
Builds for a foreign architecture use QEMU emulation (slow) or native builders per platform; compiled languages can often cross-compile instead (GOARCH=arm64).
The code
for img in python:3.14-slim nginx:1.29-alpine gcr.io/distroless/static-debian13; do
platforms=$(docker buildx imagetools inspect "$img" --format '{{json .Manifest}}' |
python3 -c 'import json,sys; m=json.load(sys.stdin); print(" ".join(sorted({p["platform"]["os"]+"/"+p["platform"]["architecture"] for p in m.get("manifests", []) if p.get("platform", {}).get("os") != "unknown"})))')
echo "$img: $platforms"
done
echo "local alpine:3.24 was pulled for: $(docker image inspect alpine:3.24 --format '{{.Os}}/{{.Architecture}}')"
Output
python:3.14-slim: linux/386 linux/amd64 linux/arm linux/arm64 linux/ppc64le linux/riscv64 linux/s390x nginx:1.29-alpine: linux/386 linux/amd64 linux/arm linux/arm64 linux/ppc64le linux/riscv64 linux/s390x gcr.io/distroless/static-debian13: linux/amd64 linux/arm linux/arm64 linux/ppc64le linux/riscv64 linux/s390x local alpine:3.24 was pulled for: linux/amd64
Run this on your computer — see “Get Started” for setup.
Common mistakes
- Building on an arm64 laptop and pushing straight to an amd64 cluster.
- Assuming every base image supports every architecture; check with
imagetools inspect. - Emulating slow builds on QEMU when the language can cross-compile.
- Native dependencies (C extensions) that have no wheel or binary for one of the platforms.
Key points
- Images are per platform; a multi-platform tag is an index of per-platform images.
- Build and push both amd64 and arm64 with
docker buildx build --platform. - Prefer cross-compilation or native builders over emulation for speed.
Further reading: Multi-platform builds · docker buildx imagetools
Practice questions
What causes 'exec format error' when starting a container?
Answer
The image's binaries were built for a different CPU architecture than the host, for example an arm64 image on an amd64 server.
What is a multi-platform image?
Answer
An image index (manifest list) under one tag that points to separate images for each platform; clients pull the one matching their OS and architecture.
Why is cross-compilation often better than QEMU emulation for multi-platform builds?
Answer
Compiling natively for the target architecture (for example GOARCH=arm64) is much faster than running the whole build under emulation.
Open in the app to mark lessons complete, take notes and track your progress.