ein Build, eine Manifest-Liste, mehrere CPU-Architekturen
Multi-Arch Images lösen das Problem, dass ein Team auf Apple-Silicon-Laptops entwickelt, aber auf amd64-Servern deployt, oder umgekehrt arm64-Instanzen in der Produktion nutzt. Docker Buildx erzeugt aus einem einzigen Build-Kommando Images für mehrere Architekturen und veröffentlicht sie unter einem gemeinsamen Tag als Manifest-Liste.
Inhaltsverzeichnis
- 1. Warum Multi-Arch Images heute Pflicht sind
- 2. Buildx-Grundlagen: Builder-Instanzen und Treiber
- 3. QEMU-Emulation: Cross-Plattform-Builds ohne fremde Hardware
- 4. Native Builder statt Emulation für produktive Pipelines
- 5. Manifest-Listen verstehen: ein Tag, mehrere Architekturen
- 6. Dockerfile-Anpassungen für Multi-Arch-Kompatibilität
- 7. Multi-Arch-Builds in GitLab CI und GitHub Actions
- 8. Multi-Arch für PHP-Extensions und native Abhängigkeiten
- 9. QEMU-Emulation im Vergleich zu nativen Buildern
- 10. Zusammenfassung
- 11. FAQ
1. Warum Multi-Arch Images heute Pflicht sind
Seit Apple mit den M-Chips vollständig auf arm64 umgestiegen ist und Cloud-Anbieter wie AWS mit Graviton-Instanzen arm64-Server zu deutlich günstigeren Preisen anbieten, reicht ein einzelnes amd64-Image nicht mehr aus. Ein Multi-Arch Image bündelt Varianten für mehrere CPU-Architekturen unter einem einzigen Tag, sodass Docker beim Pull automatisch die passende Variante für die lokale Architektur auswählt, ohne dass Entwickler oder Deployment-Skripte manuell zwischen amd64 und arm64 unterscheiden müssen.
Ohne Multi-Arch Images entstehen in der Praxis zwei unangenehme Szenarien. Entweder ein Entwicklerteam mit MacBooks der M-Serie erlebt auf Produktionsservern subtile Unterschiede, weil das lokal getestete Image unter Emulation lief, das Produktions-Image aber nativ. Oder Teams pflegen zwei getrennte Image-Tags, etwa app:1.0-amd64 und app:1.0-arm64, was Deployment-Skripte verkompliziert und Fehlerquellen für falsch gezogene Tags schafft. Docker Buildx löst genau dieses Problem, indem es beide Varianten in einem einzigen Build-Vorgang erzeugt.
Für Magento-Shops mit Docker-Entwicklungsumgebungen auf Apple-Silicon-Laptops und amd64-Produktionsservern ist ein Multi-Arch Image keine Kür mehr, sondern eine Grundvoraussetzung dafür, dass lokal getestetes Verhalten dem Produktionsverhalten entspricht. Buildx ist seit Docker 19.03 als Plugin integriert und seit Docker 23 der Standard-Builder für docker build.
2. Buildx-Grundlagen: Builder-Instanzen und Treiber
Buildx erweitert die klassische docker build-Engine um BuildKit-Funktionen und mehrere Builder-Treiber. Der Standardtreiber docker nutzt den lokalen Docker-Daemon und unterstützt keine Multi-Plattform-Builds. Für Multi-Arch Images braucht es den Treiber docker-container, der einen dedizierten BuildKit-Container startet, oder den Treiber kubernetes für verteilte Builds über mehrere Kubernetes-Pods hinweg.
Eine Builder-Instanz wird einmalig mit docker buildx create angelegt und danach über ihren Namen wiederverwendet. Mehrere Builder-Instanzen können parallel existieren, etwa ein lokaler Builder für die Entwicklung und ein Remote-Builder für native arm64-Kompilierung. Das Kommando docker buildx ls zeigt alle registrierten Builder mit ihren unterstützten Plattformen, docker buildx inspect --bootstrap startet einen Builder und prüft dessen Fähigkeiten.
# Create a dedicated buildx builder with the docker-container driver
docker buildx create --name multiarch-builder --driver docker-container --use
# Bootstrap the builder and list supported platforms
docker buildx inspect --bootstrap
# List all registered builders
docker buildx ls
# Build and push a multi-arch image in a single command
docker buildx build \
--platform linux/amd64,linux/arm64 \
--tag registry.mironsoft.de/shop-app:1.4.0 \
--push .
3. QEMU-Emulation: Cross-Plattform-Builds ohne fremde Hardware
Um ein Multi-Arch Image auf einer einzigen amd64-Maschine für arm64 zu bauen, nutzt Buildx standardmäßig QEMU als Benutzerraum-Emulator. Der Kernel führt fremde Instruktionen über binfmt_misc-Handler transparent an QEMU weiter, das die arm64-Instruktionen Zeile für Zeile in native amd64-Instruktionen übersetzt. Das funktioniert zuverlässig, ist aber deutlich langsamer als native Ausführung, typischerweise um den Faktor fünf bis zehn bei rechenintensiven Build-Schritten wie Compiler-Läufen.
Auf Standard-Linux-Hosts müssen die QEMU-Handler oft erst registriert werden, was über das Image tonistiigi/binfmt geschieht. Docker Desktop bringt diese Registrierung bereits vorkonfiguriert mit. Für einfache PHP-Anwendungen ohne native Compiler-Schritte ist die QEMU-Emulation meist ausreichend performant, weil der eigentliche Flaschenhals die Composer-Installation und das Kopieren von Dateien ist, nicht CPU-intensive Kompilierung.
# Register QEMU handlers for cross-platform emulation on a plain Linux host
docker run --privileged --rm tonistiigi/binfmt --install all
# Verify that arm64 emulation is now available
docker buildx inspect --bootstrap | grep Platforms
# Build only the arm64 variant for local testing, without pushing
docker buildx build --platform linux/arm64 --tag shop-app:arm64-test --load .
4. Native Builder statt Emulation für produktive Pipelines
Für Projekte mit nativen Compiler-Schritten, etwa das Kompilieren von PHP-Extensions aus dem Quellcode oder das Bauen von Node-Modulen mit nativen Bindings, wird die QEMU-Emulation schnell zum Flaschenhals in der CI-Pipeline. Die deutlich schnellere Alternative ist ein echter native Builder: eine zweite Buildx-Instanz, die auf einem tatsächlichen arm64-Host läuft, etwa einer AWS-Graviton-Instanz oder einem Apple-Silicon-Runner, und über SSH oder das Kubernetes-Backend als Remote-Builder eingebunden wird.
Mit docker buildx create --append lässt sich ein zweiter Node zu einer bestehenden Builder-Instanz hinzufügen, sodass ein einziger buildx build-Aufruf die amd64-Variante nativ auf dem lokalen Host und die arm64-Variante nativ auf dem angehängten Remote-Node baut. Buildx orchestriert dabei automatisch, welcher Node welchen Teil des Multi-Arch Image übernimmt, ohne dass der Entwickler das Kommando anpassen muss.
# Append a native arm64 remote node via SSH to the existing builder
docker buildx create --name multiarch-builder --append \
--node arm64-native \
--platform linux/arm64 \
ssh://build-user@arm64-runner.internal
# Bootstrap both nodes and verify the combined platform list
docker buildx inspect --bootstrap
# Now the same build command uses native compilation on both architectures
docker buildx build --platform linux/amd64,linux/arm64 \
--tag registry.mironsoft.de/shop-app:1.4.0 --push .
5. Manifest-Listen verstehen: ein Tag, mehrere Architekturen
Das technische Fundament von Multi-Arch Images ist die OCI Image Index Spezifikation, in Docker-Terminologie auch Manifest-Liste genannt. Statt eines einzelnen Image-Manifests mit einer Layer-Liste enthält der Index mehrere Manifest-Einträge, jeweils annotiert mit Architektur und Betriebssystem. Ein Docker-Client, der registry.mironsoft.de/shop-app:1.4.0 zieht, fragt zunächst den Index ab und lädt danach ausschließlich das zur eigenen Plattform passende Manifest samt Layern.
Der entscheidende Vorteil: Registries wie Docker Hub, GitLab Container Registry oder AWS ECR unterstützen diese Struktur nativ, sodass keine separate Logik im Deployment nötig ist. Mit docker manifest inspect registry.mironsoft.de/shop-app:1.4.0 lässt sich die vollständige Liste der enthaltenen Architekturen einsehen, ohne das Image tatsächlich herunterladen zu müssen.
# Inspect the manifest list of a multi-arch image without pulling it
docker manifest inspect registry.mironsoft.de/shop-app:1.4.0
# Output shows one entry per architecture, for example:
# linux/amd64 -> sha256:aaa...
# linux/arm64 -> sha256:bbb...
# docker pull automatically selects the matching manifest
docker pull registry.mironsoft.de/shop-app:1.4.0
6. Dockerfile-Anpassungen für Multi-Arch-Kompatibilität
Die meisten Dockerfiles funktionieren ohne Änderung für Multi-Arch Images, sofern die Basis-Images selbst schon Multi-Arch-fähig sind, was für die offiziellen Images wie php, node oder debian heute Standard ist. Buildx setzt automatisch die eingebauten Argumente TARGETARCH, TARGETOS und TARGETPLATFORM, mit denen sich architekturspezifische Downloads oder Binaries im Dockerfile gezielt steuern lassen.
Problematisch werden Dockerfiles nur, wenn sie fest verdrahtete amd64-Annahmen enthalten, etwa den direkten Download einer amd64-only-Binary per URL. Der korrekte Multi-Arch-Ansatz nutzt ARG TARGETARCH und wählt darüber die richtige Download-URL, statt die Architektur hart zu kodieren.
FROM --platform=$BUILDPLATFORM php:8.4-fpm AS base
# Buildx sets these automatically for the target platform
ARG TARGETARCH
ARG TARGETOS
# Download an architecture-specific binary based on TARGETARCH
RUN case "$TARGETARCH" in \
amd64) BIN_ARCH="x86_64" ;; \
arm64) BIN_ARCH="aarch64" ;; \
*) echo "Unsupported architecture: $TARGETARCH" && exit 1 ;; \
esac && \
curl -sSL "https://example.com/tool-${BIN_ARCH}.tar.gz" | tar -xz -C /usr/local/bin
7. Multi-Arch-Builds in GitLab CI und GitHub Actions
In CI-Pipelines lohnt sich der Einsatz eines dedizierten docker-container-Builders innerhalb eines Docker-in-Docker-Runners, kombiniert mit einem Cache-Backend wie der Registry selbst, um wiederholte QEMU-Emulation über mehrere Pipeline-Läufe hinweg zu vermeiden. GitHub Actions bietet mit docker/setup-qemu-action und docker/setup-buildx-action vorgefertigte Schritte, die Registrierung und Builder-Erstellung übernehmen, bevor der eigentliche build-push-action läuft.
GitLab-Runner mit Docker-Executor benötigen die manuelle Registrierung der QEMU-Handler über das tonistiigi/binfmt-Image als vorgeschalteten Job-Schritt, weil GitLab keinen vergleichbaren fertigen Action-Baustein bereitstellt. Für Teams mit hohem Build-Volumen zahlt sich ein separater arm64-Runner deutlich schneller aus als dauerhafte QEMU-Emulation in jeder Pipeline.
# GitLab CI: multi-arch build with QEMU registration and buildx
build-multiarch:
stage: build
image: docker:27
services: [docker:27-dind]
before_script:
- docker run --privileged --rm tonistiigi/binfmt --install all
- docker buildx create --name ci-builder --driver docker-container --use
- docker buildx inspect --bootstrap
script:
- docker buildx build --platform linux/amd64,linux/arm64 \
--tag "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA" --push .
8. Multi-Arch für PHP-Extensions und native Abhängigkeiten
PHP-Extensions mit nativem C-Code, etwa gd, intl oder imagick, werden im Dockerfile über docker-php-ext-install aus dem Quellcode kompiliert und sind damit automatisch architekturunabhängig, weil der Compiler auf jedem Zielsystem für die jeweilige Architektur übersetzt. Ein Multi-Arch Image für PHP erfordert deshalb selten Sonderbehandlung, solange keine vorkompilierten Binärpakete für eine feste Architektur eingebunden werden.
Kritischer wird es bei Composer-Paketen mit nativen Erweiterungen, etwa Bibliotheken, die eigene .so-Dateien mitbringen, oder bei Node-Abhängigkeiten mit nativen Bindings wie sharp für Bildverarbeitung. Diese Pakete führen bei jedem npm install oder composer install plattformspezifische Post-Install-Skripte aus, die zwingend auf der Zielarchitektur laufen müssen, weshalb die Installation innerhalb der jeweiligen Build-Stage stattfinden muss, statt Artefakte zwischen Architekturen zu kopieren.
9. QEMU-Emulation im Vergleich zu nativen Buildern
Die Entscheidung zwischen QEMU-Emulation und nativen Buildern für Multi-Arch Images hängt von Build-Komplexität, verfügbarer Infrastruktur und Team-Größe ab. Die folgende Tabelle vergleicht beide Ansätze entlang der wichtigsten Praxiskriterien.
| Kriterium | QEMU-Emulation | Native Builder |
|---|---|---|
| Setup-Aufwand | Gering, ein Docker-Kommando | Höher, zusätzlicher Host oder Runner nötig |
| Build-Geschwindigkeit | Fünf bis zehn Mal langsamer | Native Geschwindigkeit |
| Infrastrukturkosten | Keine zusätzlichen | Zweite Hostklasse notwendig |
| Geeignet für | Einfache PHP/Node-Builds ohne Compiler-Last | Compiler-lastige Builds, hohe CI-Frequenz |
| Fehleranfälligkeit | Seltene Emulator-Bugs bei exotischen Syscalls | Keine emulationsbedingten Fehler |
Für kleinere Teams und Projekte ohne hohe Build-Frequenz ist QEMU-Emulation der pragmatische Standardweg, weil kein zusätzlicher Host verwaltet werden muss. Sobald Build-Zeiten in der CI-Pipeline spürbar zur Belastung werden, amortisiert sich ein zweiter nativer Builder-Node innerhalb weniger Wochen durch eingesparte Wartezeit und CI-Minuten.
Mironsoft
Docker-Buildstrategien für Apple-Silicon-Teams und arm64-Produktion
Multi-Arch Images für euer Team einrichten?
Wir richten Buildx-Builder für amd64 und arm64 ein, wählen zwischen QEMU-Emulation und nativen Remote-Buildern und integrieren Multi-Arch-Builds sauber in eure GitLab- oder GitHub-Pipeline.
Buildx-Setup
Builder-Instanzen, QEMU-Registrierung und native Remote-Nodes konfigurieren
Dockerfile-Audit
Architekturabhängige Annahmen finden und mit TARGETARCH sauber lösen
CI-Integration
Multi-Arch-Builds mit Caching in eure bestehende Pipeline einbauen
10. Zusammenfassung
Multi-Arch Images mit Docker Buildx lösen das wachsende Problem unterschiedlicher CPU-Architekturen zwischen Entwicklungslaptops und Produktionsservern, indem ein einziger Build-Vorgang Varianten für amd64 und arm64 erzeugt und unter einem gemeinsamen Tag als Manifest-Liste veröffentlicht. QEMU-Emulation ermöglicht Cross-Plattform-Builds auf einer einzigen Maschine, ist aber deutlich langsamer als native Builder, die auf tatsächlicher Zielarchitektur-Hardware laufen und über Remote-Nodes in dieselbe Builder-Instanz eingebunden werden.
Die meisten Dockerfiles benötigen keine Änderung für Multi-Arch Images, sofern die Basis-Images selbst Multi-Arch-fähig sind und keine fest kodierten amd64-Annahmen im Build enthalten sind. Für PHP-Anwendungen ist der Aufwand meist gering, weil native Extensions ohnehin pro Zielsystem kompiliert werden. Kritisch bleibt lediglich die Behandlung vorkompilierter Binärpakete und nativer Node-Module, deren Installation zwingend in der jeweiligen Ziel-Stage stattfinden muss.
Multi-Arch Images mit Docker Buildx — Das Wichtigste auf einen Blick
Buildx-Builder
docker buildx create --driver docker-container ist Voraussetzung für Multi-Plattform-Builds, der Standard-Docker-Treiber reicht nicht.
QEMU vs. nativ
QEMU emuliert bequem auf einer Maschine, native Remote-Nodes sind fünf bis zehn Mal schneller bei Compiler-Lasten.
Manifest-Liste
Ein Tag, mehrere Architektur-Manifeste. Docker wählt beim Pull automatisch das passende aus.
TARGETARCH
Von Buildx automatisch gesetztes Build-Argument, steuert architekturspezifische Downloads im Dockerfile.