Images für ARM und AMD64 bauen - Docker Buildx und Multi-Platform

Images für ARM und AMD64 bauen - Docker Buildx und Multi-Platform

Raspberry Pi, Apple Silicon (M1/M2/M3), AWS Graviton — ARM-basierte Systeme sind keine Ausnahme mehr. Ein Image für mehrere Plattformen zu bauen ist mit docker buildx einfacher als man denkt.

Warum das relevant ist

Ein Image, das auf AMD64 (x86_64) gebaut wurde, läuft auf ARM nicht nativ — der Kernel emuliert die andere Architektur, was deutlich langsamer ist. Native ARM-Images laufen auf ARM-Hardware ohne Overhead.

Mit Multi-Platform-Builds liefert docker pull automatisch das zur Plattform passende Image.

Buildx einrichten

Buildx ist seit Docker 19.03 enthalten, muss aber als aktiver Builder eingerichtet werden:

# Neuen Builder erstellen und aktivieren
docker buildx create --name multibuilder --use

# QEMU für Cross-Compilation installieren (einmalig)
docker run --privileged --rm tonistiigi/binfmt --install all

# Builder prüfen
docker buildx inspect --bootstrap

Der Builder zeigt die unterstützten Plattformen:

Platforms: linux/amd64, linux/arm64, linux/arm/v7, linux/386

Multi-Platform-Image bauen und pushen

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myregistry/myapp:1.2.3 \
  --push \
  .

--push ist hier notwendig — Multi-Platform-Images können nicht in den lokalen Docker-Cache geladen werden, weil der lokale Cache nur eine Plattform hält. Das Image geht direkt in die Registry.

Manifest prüfen

Ob ein Image wirklich für mehrere Plattformen verfügbar ist:

docker manifest inspect myregistry/myapp:1.2.3

Im Output sind alle Plattform-Varianten mit ihren Digests aufgelistet.

Plattform-spezifische Logik im Dockerfile

In seltenen Fällen braucht man plattformabhängige Befehle. BUILDPLATFORM und TARGETPLATFORM sind eingebaute Build-Argumente:

FROM --platform=$BUILDPLATFORM golang:1.21 AS builder
ARG TARGETPLATFORM
ARG TARGETOS
ARG TARGETARCH

WORKDIR /app
COPY . .
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o server .

FROM alpine:3.18
COPY --from=builder /app/server /app/server
CMD ["/app/server"]

Go cross-kompiliert nativ — kein QEMU nötig, der Build läuft auf dem Build-Host in voller Geschwindigkeit.

Wann native Builder sinnvoll sind

QEMU-Emulation funktioniert für die meisten Builds — aber bei aufwändigen nativen Compilierungen (C-Extensions, Rust) ist die Emulation deutlich langsamer. In diesem Fall: nativen ARM-Builder über docker buildx create --append zum Builder-Pool hinzufügen, damit jede Plattform nativ gebaut wird.