buildx + multi-arch cheatsheet.
Buildx basics
docker buildx ls # builders
docker buildx create --name mybuilder --use
docker buildx inspect --bootstrap
docker buildx build . # uses BuildKit
Multi-platform build
docker buildx build --platform linux/amd64,linux/arm64 -t myapp:v1 --push .
Must push (no local multi-arch storage by default).
Push vs load
docker buildx build --load -t myapp . # load into local docker (single platform)
docker buildx build --push -t myapp . # push to registry
docker buildx build --output type=tar,dest=out.tar .
Cache export
docker buildx build \
--cache-to type=registry,ref=myreg/cache:latest,mode=max \
--cache-from type=registry,ref=myreg/cache:latest \
-t myapp .
Persist build cache in a registry.
Local cache
docker buildx build \
--cache-to type=local,dest=./cache \
--cache-from type=local,src=./cache \
-t myapp .
inline cache
docker buildx build \
--cache-to type=inline \
-t myreg/myapp:latest --push .
# Next build uses image as cache source
docker buildx build \
--cache-from type=registry,ref=myreg/myapp:latest \
-t myreg/myapp:next --push .
Cache stored in image itself.
GitHub Actions cache
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: myreg/myapp:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
type=gha uses GitHub Actions cache — fastest for GitHub-hosted runners.
Bake (multi-target)
# docker-bake.hcl
group "default" {
targets = ["web", "worker"]
}
target "web" {
context = "."
dockerfile = "Dockerfile.web"
platforms = ["linux/amd64", "linux/arm64"]
tags = ["myreg/web:v1"]
}
target "worker" {
context = "."
dockerfile = "Dockerfile.worker"
tags = ["myreg/worker:v1"]
}
docker buildx bake
docker buildx bake --push
docker buildx bake web # one target
Cross-compile (faster than QEMU)
For ARM build on AMD64 host without emulation overhead, use Go’s GOARCH or set up cross-toolchain in Dockerfile.
FROM --platform=$BUILDPLATFORM golang:1.22 AS build
ARG TARGETOS TARGETARCH
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /out/app .
FROM scratch
COPY --from=build /out/app /app
ENTRYPOINT ["/app"]
Native build for each target arch.
QEMU (for non-Go languages)
docker run --rm --privileged tonistiigi/binfmt --install all
Enables ARM emulation on AMD64 host. Slow but works for anything.
OCI manifest
buildx --push creates an OCI manifest list (multi-arch image). Pulling auto-selects host arch.
docker buildx imagetools inspect myreg/myapp:v1
Provenance + SBOM
docker buildx build \
--provenance=true \
--sbom=true \
-t myreg/myapp:v1 --push .
Attaches build metadata. View:
docker buildx imagetools inspect --format '{{json .Provenance}}' myreg/myapp:v1
docker scout sbom myreg/myapp:v1
Remote builder
docker buildx create \
--name remote-builder \
--driver docker-container \
--driver-opt image=moby/buildkit:latest \
--buildkitd-flags '--allow-insecure-entitlement security.insecure' \
ssh://user@buildhost
Offload builds to a beefy machine.
Kubernetes-driven builder
docker buildx create \
--driver kubernetes \
--name k8s-builder \
--node mybuilder
Use cluster resources for builds.
Buildx in CI strategy
- uses: docker/login-action@v3
with: { registry: ghcr.io, username: ..., password: ... }
- uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.ref == 'refs/heads/main' }}
tags: |
ghcr.io/me/myapp:latest
ghcr.io/me/myapp:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
Common mistakes
--loadwith multi-platform → only one platform stored.- Forgetting
--platform→ builds for build host arch only. - QEMU emulation for slow builds — try cross-compile.
- Cache mode
minvsmax—maxincludes intermediate stages. - Push without auth — silent failures or
denied.
Read this next
If you want my buildx + bake templates, they’re at rajpoot.dev .
Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .