Docker cookbook · Intermediate
Build one image tag for amd64 and arm64
Run the same image on x86 servers, ARM servers and Apple Silicon laptops.
Approach
Use Buildx with --platform linux/amd64,linux/arm64 and push; the tag becomes an index pointing to one image
per platform. Cross-compile where the language allows, otherwise use QEMU or native builders.
Solution
docker buildx create --name multi --use
docker buildx build --platform linux/amd64,linux/arm64 -t ghcr.io/acme/api:1.4.2 --push .
docker buildx imagetools inspect ghcr.io/acme/api:1.4.2
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:1.26-alpine AS build
ARG TARGETOS TARGETARCH
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /out/app .
FROM gcr.io/distroless/static-debian13:nonroot
COPY --from=build /out/app /app
ENTRYPOINT ["/app"]
Pitfalls
- Building on an arm64 laptop and pushing straight to amd64 production (
exec format error). - Emulating a whole compile under QEMU when the compiler can cross-compile.
Variations
- Native arm64 CI runners for languages that can't cross-compile easily.
docker buildx baketo define many targets and platforms in one file.
Further reading: Multi-platform builds
Reference: https://docs.docker.com/build/building/multi-platform/
More Docker recipes
- Add a healthcheck to an HTTP service
- Build a layered image for a Spring Boot app
- Build a production image for a Node.js service
- Build a production image for a Python web app
- Build, cache and push images in GitHub Actions
- Configure nginx from environment variables
- Develop with Compose and live reload
- Make containers cope with dependencies that start slowly