arm64 bevorzugen, amd64 bei Bedarf
Ein Mac der M-Serie führt Linux-Container auf einem arm64-Linux-Kernel aus. Wenn du ein Image für mehrere Architekturen herunterlädst (postgres, redis, node, python und die meisten offiziellen Images), wählt Docker automatisch die arm64-Variante, die mit nativer Geschwindigkeit läuft.
Manche Images gibt es weiterhin nur für amd64: ältere interne Images, Herstellerwerkzeuge und alles, was auf einem Intel-Laptop oder einem CI-Runner ohne Plattform-Flag gebaut wurde. Gib es für diese ausdrücklich an:
services:
legacy-tool:
image: example/amd64-only-tool:1.4
platform: linux/amd64 Oxcart führt amd64-Images über Rosetta aus, Apples x86-64-Übersetzung. Buildx kann amd64-Images bauen und laden, die die Engine anschließend lokal ausführt. Prüfe mit docker run --rm --platform linux/amd64 alpine uname -m, als welche Architektur ein Container tatsächlich läuft; die Ausgabe lautet x86_64.
| Situation | Vorgehen |
|---|---|
| Image bietet arm64 an | Nichts. Compose lädt die arm64-Variante herunter. |
| Image gibt es nur für amd64 | Füge dem Service platform: linux/amd64 hinzu. |
| Du stellst auf amd64-Servern bereit | Baue das Image zum Pushen mit docker buildx build --platform linux/amd64; bleib für lokale Arbeit bei arm64, wenn dein Stack es zulässt. |
| „exec format error“ | Eine Binärdatei passt nicht zur Architektur des Containers. Setze die Plattform oder baue für arm64 neu. |
Ein vollständiges Beispiel
Eine Postgres-Datenbank, eine API aus dem aktuellen Ordner, die wartet, bis die Datenbank gesund ist, und ein nur für amd64 verfügbares Werkzeug hinter einem Profil:
services:
db:
image: postgres:17-alpine
environment:
POSTGRES_PASSWORD: dev
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 2s
timeout: 3s
retries: 15
api:
build: .
init: true
environment:
DATABASE_URL: postgres://postgres:dev@db:5432/postgres
ports:
- "127.0.0.1:8080:8080"
depends_on:
db:
condition: service_healthy
legacy-tool:
image: example/amd64-only-tool:1.4
platform: linux/amd64
profiles: ["tools"]
volumes:
pgdata: Was die einzelnen Teile tun:
healthchecksagt Compose, wann Postgres tatsächlich Verbindungen annimmt und nicht nur gestartet ist.depends_on: condition: service_healthylässt die API warten, bis diese Prüfung erfolgreich ist.init: truestartet ein kleines Init als PID 1, damit Signale deinen Prozess erreichen und Zombieprozesse eingesammelt werden.docker stopbeendet ihn dann sauber, statt auf den Timeout zu warten.127.0.0.1:8080:8080veröffentlicht die API nur auf dem Loopback deines Macs. Ohne Adresse lauscht ein veröffentlichter Port auf allen IPv4-Adressen des Macs und ist von anderen Geräten in deinem Netzwerk erreichbar.pgdataist ein benanntes Volume: Die Daten überstehendocker compose downund werden erst durchdown -vgelöscht.
Einen Compose-Stack auf Apple-Chips ausführen
- Prüfe die Werkzeuge. Führe
docker compose versionunddocker context showaus. Oxcart enthält Docker Compose 5.6.0 mit der docker-CLI 29.9.0 und Buildx 0.38.0; sein Kontext heißtoxcart. - Schreibe die Compose-Datei. Gib jedem Service, auf den deine App wartet, einen
healthcheckund lasse abhängige Services mitdepends_on: condition: service_healthywarten. - Starte und warte auf einen gesunden Zustand. Führe
docker compose up -d --build --waitaus. Der Befehl kehrt zurück, sobald jeder Service läuft und gesund ist, oder schlägt fehl, wenn einer es nicht ist. - Prüfe die Ports. Führe
docker compose psaus oder öffne die Ansicht Ports in Oxcart. Sie zeigt jeden veröffentlichten Port als bereit, ausstehend oder fehlgeschlagen an, samt Ursache. - Entwickle weiter. Ändere den Code und führe
docker compose up -d --build apiaus. Unveränderte Build-Schritte kommen aus dem Cache. - Beende und entferne die Container. Führe
docker compose downaus, um die Container zu stoppen und zu entfernen, oderdocker compose down -v, um auch die benannten Volumes zu löschen.
Schnellere erneute Builds
Compose baut über Buildx und BuildKit. Ordne dein Dockerfile so, dass Abhängigkeiten vor COPY . . installiert werden. Bei einer Codeänderung werden dann alle darüberliegenden gecachten Schichten wiederverwendet. In Oxcart dauerte ein Build des Benchmark-Projekts mit Cache 121 ms und ohne Cache mit lokalem Kontext 341 ms: jeweils am schnellsten unter den drei getesteten Laufzeitumgebungen. Kurze Entwicklungszyklen summieren sich: docker run --rm dauerte 42 ms, das Stoppen und Entfernen von 20 Containern 77 ms.
Oxcart 0.1.2 wurde am 2026-10-10 mit dem mitgelieferten docker-Client 29.9 gemessen; die anderen Laufzeitumgebungen früher am selben Tag auf demselben Mac mit demselben Messaufbau und docker 29.4. Apple M5 Max, jeweils 8 CPUs und 12 GiB, eine Laufzeitumgebung nach der anderen.
Ports, der Mac und andere Services
- Die Portsyntax entspricht Docker: TCP und UDP, dynamisch vergebene Ports (
"127.0.0.1::8080") und"[::]:8080:80"zum Lauschen auf IPv4 und IPv6. TCP und UDP können dieselbe Host-Portnummer verwenden. - Der Mac aus einem Container:
host.docker.internalerreicht über TCP Dienste, die an127.0.0.1des Macs gebunden sind, aus Containern und Build-Schritten. - Eine lokale Registry: Veröffentliche einen Registry-Container auf Port 5000, und
docker push localhost:5000/apperreicht ihn. - Sidecars:
network_mode: service:apiversetzt einen Container in den Netzwerk-Namespace eines anderen Services, sodass er dessenlocalhostteilt.
Zu VPNs, DNS, Firewalls und dem Schutz des Netzwerkwegs siehe Containernetzwerke auf dem Mac.
Benannte Volumes und Bind-Mounts
Verwende benannte Volumes für alles, worauf die Datenbank oder der Build viel schreibt: node_modules, Paket-Caches und Datenbankdateien. Ihre Daten bleiben im Speicher der Engine. In Oxcart führte ein benanntes Volume 1,000 Operationen zum Erstellen, stat-Abfragen, Lesen und Löschen kleiner Dateien in 17.8 ms aus, am schnellsten unter den drei getesteten Laufzeitumgebungen.
Verwende Bind-Mounts für Quellcode, den du auf deinem Mac bearbeitest. Standardmäßig gibt Oxcart deinen Benutzerordner, /private/tmp und /private/var/folders mit Lese- und Schreibzugriff für Container frei. Änderungen auf dem Mac erscheinen in Containern und Änderungen in Containern auf dem Mac. Eine wichtige Grenze: Dateiänderungen auf dem Mac erzeugen keine inotify-Ereignisse in Containern. Ein Dateiwächter im Container sollte daher Polling verwenden, wenn er Änderungen aus deinem Editor erkennen muss.
Fehlerbehebung
| Symptom | Ursache | Lösung |
|---|---|---|
exec format error | amd64-Binärdatei in einem arm64-Container oder umgekehrt | platform: linux/amd64 oder für arm64 neu bauen |
| „no matching manifest for linux/arm64“ | Das Image hat keine arm64-Variante | platform: linux/amd64 |
| „address already in use“ | Ein anderer Prozess oder Container belegt den Host-Port | Host-Port ändern oder den Besitzer in Oxcarts Ansicht Ports finden |
| Verbindung auf einem veröffentlichten Port abgelehnt | Der Server lauscht im Container auf 127.0.0.1, oder noch nichts lauscht | Auf 0.0.0.0 lauschen; einen Healthcheck hinzufügen und --wait verwenden |
| App startet, bevor die Datenbank bereit ist | depends_on ohne Bedingung wartet nur auf den Start | condition: service_healthy plus a healthcheck |
docker stop wartet 10 s | PID 1 ignoriert SIGTERM | init: true oder SIGTERM in der App behandeln |
Fragen
Funktioniert Docker Compose auf Macs mit Apple-Chip?
Ja. Compose läuft nativ auf arm64, und die meisten offiziellen Images bieten arm64-Varianten. Oxcart enthält Docker Compose 5.6.0. Die Kompatibilitätsprüfungen decken mehrere Services, Healthcheck-Abhängigkeiten, up --wait, build, down, DNS über Servicenamen, init: true und network_mode: service: ab.
Wie führe ich ein amd64-Image (x86-64) auf einem Mac der M-Serie aus?
Setze platform: linux/amd64 beim Service oder übergib --platform linux/amd64 an docker run. Oxcart führt amd64-Images über Rosetta aus. Bevorzuge ein natives arm64-Image, wenn eines existiert; verwende amd64 für Images ohne arm64-Build.
Was bedeutet „exec format error“?
Der Container hat versucht, eine Binärdatei für eine andere CPU-Architektur auszuführen als die, unter der er läuft. Meist ist ein Image oder eine darin enthaltene Binärdatei nur für amd64 verfügbar. Füge dem Service platform: linux/amd64 hinzu oder baue das Image für arm64 neu.
Warum meldet meine App „connection refused“, obwohl der Container läuft?
Die häufigste Ursache ist ein Server, der im Container auf 127.0.0.1 lauscht. Veröffentlichte Ports erreichen die Netzwerkschnittstelle des Containers, nicht seinen Loopback. Der Server muss daher auf 0.0.0.0 lauschen. Oxcarts Ansicht Ports benennt diesen Fall ausdrücklich.
Wie lasse ich einen Service warten, bis ein anderer bereit ist?
Füge der Abhängigkeit einen healthcheck und dem abhängigen Service depends_on: { db: { condition: service_healthy } } hinzu. docker compose up --wait kehrt dann erst zurück, wenn jeder Service gesund ist.
Können Container einen Server auf meinem Mac erreichen?
Ja. Verwende host.docker.internal: In Oxcart erreicht es über TCP Dienste, die an 127.0.0.1 des Macs gebunden sind, aus Containern und Builds.
Sollte ich für Datenbanken benannte Volumes oder Bind-Mounts verwenden?
Verwende für Datenbankdaten ein benanntes Volume: Es liegt im eigenen Speicher der Engine. Verwende Bind-Mounts für Quellcode, den du auf dem Mac bearbeitest. In Oxcart führte ein benanntes Volume 1,000 Operationen zum Erstellen, stat-Abfragen, Lesen und Löschen kleiner Dateien in 17.8 ms aus.
Quellen und Methode
- Kompatibilität: Oxcarts geprüfte Integrationswege (docker-CLI, Compose mit Healthcheck-Abhängigkeiten,
up --wait,init: true,network_mode: service:, Buildx, amd64 über Rosetta). - Geschwindigkeitswerte: Oxcart 0.1.2, 2026-10-10, Apple M5 Max, 8 CPUs und 12 GiB, Mediane aus fünf Messungen nach einem Aufwärmdurchlauf; die anderen Laufzeitumgebungen wurden früher am selben Tag auf demselben Mac mit demselben Messaufbau und dem docker-Client 29.4 gemessen.
- Mitgelieferte Werkzeuge: docker 29.9.0, Docker Compose 5.6.0, Buildx 0.38.0.