Volumes, Sync, OPcache und Hyvä-Watcher
Eine langsame Magento-Docker-Umgebung bremst jeden Entwicklungszyklus aus. Mit der richtigen Volume-Strategie, Mutagen-Sync, korrekt konfiguriertem OPcache und einem laufenden Hyvä-Watcher lässt sich die wahrgenommene Geschwindigkeit drastisch verbessern – ohne auf die Isolationsvorteile von Docker zu verzichten.
Inhaltsverzeichnis
- 1. Das Performanceproblem bei Magento in Docker
- 2. Volume-Typen und ihre Auswirkungen auf Magento
- 3. Mutagen-Sync: Datei-Synchronisation ohne Bind-Mount-Overhead
- 4. OPcache in Docker richtig konfigurieren
- 5. Generated-Ordner und var-Cache aus dem Sync ausschließen
- 6. Hyvä CSS-Watcher im Container betreiben
- 7. Entwicklungs-Compose-Override optimal aufbauen
- 8. Xdebug und OPcache im Entwicklungsmodus kombinieren
- 9. Volume-Strategien im direkten Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Das Performanceproblem bei Magento in Docker
Wer Magento in Docker betreibt, kennt das Problem: Eine einfache Seitenanfrage, die auf dem Host-System unter einer Sekunde liegt, braucht im Container mit Bind-Mount drei bis fünf Sekunden. Der Grund liegt nicht an Magento selbst, sondern an der Art, wie Docker auf macOS und Windows Datei-I/O zwischen Host-Dateisystem und Container-Dateisystem überbrückt. Bei einem Magento-Projekt mit Zehntausenden PHP-Dateien werden bei jeder Anfrage Hunderte stat-Aufrufe ausgeführt – jeder davon muss durch die Virtualisierungsschicht.
Das Ergebnis ist nicht nur eine langsame Seitenanfrage, sondern auch ein träger Entwicklungszyklus: bin/magento-Befehle laufen gefühlt ewig, die Composer-Installation dauert Minuten statt Sekunden, und der Hyvä-Tailwind-Build stockt beim Datei-Watching. Wer Magento in Docker produktiv entwickeln will, muss diese I/O-Schicht gezielt adressieren. Die gute Nachricht: Mit der richtigen Kombination aus Volume-Strategie, Sync-Tool und OPcache-Konfiguration verschwindet das Problem weitgehend.
2. Volume-Typen und ihre Auswirkungen auf Magento
Docker kennt drei wesentliche Volume-Typen: Bind-Mounts, benannte Volumes und tmpfs. Für Magento in Docker hat jeder Typ einen unterschiedlichen Anwendungsbereich. Bind-Mounts (./src:/var/www/html) sind die einfachste Lösung – der Code auf dem Host ist sofort im Container sichtbar. Dafür ist der I/O-Overhead auf macOS erheblich, weil das osxfs- bzw. VirtioFS-Layer jeden Dateizugriff koordinieren muss. Benannte Volumes hingegen leben vollständig im Container-Dateisystem, was nativen I/O-Speed bedeutet, aber die Code-Synchronisation erfordert einen separaten Mechanismus.
Für Magento in Docker bewährt sich eine hybride Strategie: Der Quellcode liegt in einem benannten Volume mit schnellem I/O, ein Sync-Tool hält ihn aktuell, und nur wenige ausgewählte Verzeichnisse wie app/code und app/design werden als Bind-Mounts gemountet. Verzeichnisse, die sehr viele kleine Schreibzugriffe erzeugen – var/cache, var/page_cache, generated – bekommen eigene benannte Volumes oder sogar tmpfs-Mounts, damit diese Hot-Paths nicht durch die langsame Synchronisierungsschicht gebremst werden.
# compose.dev.yaml — Hybrid volume strategy for Magento in Docker
services:
phpfpm:
volumes:
# Main source: named volume for fast I/O
- magento-src:/var/www/html
# Developer code: bind-mount only active development dirs
- ./src/app/code:/var/www/html/app/code:delegated
- ./src/app/design:/var/www/html/app/design:delegated
# Fast scratch volumes: native container I/O
- magento-var:/var/www/html/var
- magento-generated:/var/www/html/generated
- magento-static:/var/www/html/pub/static
# tmpfs for session and cache hot path
- type: tmpfs
target: /var/www/html/var/cache
- type: tmpfs
target: /var/www/html/var/page_cache
volumes:
magento-src:
magento-var:
magento-generated:
magento-static:
3. Mutagen-Sync: Datei-Synchronisation ohne Bind-Mount-Overhead
Mutagen ist ein Datei-Synchronisationstool, das speziell für schnelles bidirektionales Syncing zwischen Host und Container entwickelt wurde und in modernen Mark-Shust-Docker-Setups als Standard integriert ist. Statt eines Bind-Mounts wird der Quellcode als benanntes Volume gehandhabt. Mutagen hält Host und Container-Volume asynchron synchron – Änderungen auf dem Host werden im Hintergrund übertragen, ohne dass jeder Datei-I/O durch die langsame Cross-OS-Schicht muss. Das Ergebnis bei Magento in Docker: Seitenaufbauzeiten, die sich kaum von einem nativen Setup unterscheiden.
Die Konfiguration erfolgt über eine mutagen.yml-Datei, in der Sync-Intervall, Ignore-Patterns und Konfliktauflösung festgelegt werden. Wichtig für Magento in Docker: Verzeichnisse wie var, generated und pub/static gehören in die Ignore-Liste von Mutagen – diese werden ausschließlich im Container erzeugt und brauchen keine bidirektionale Synchronisation. Nur die Verzeichnisse, an denen Entwickler aktiv arbeiten (app/code, app/design, Template-Dateien), müssen synchron gehalten werden. Das reduziert die Sync-Last erheblich und hält Mutagen reaktiv.
4. OPcache in Docker richtig konfigurieren
OPcache ist der größte einzelne Performance-Faktor für Magento in Docker. Ohne OPcache wird jede PHP-Datei bei jedem Request neu geparst und kompiliert – bei Magento mit seiner tiefen Vererbungshierarchie sind das bei einem einzigen Request oft über tausend Dateien. OPcache cached den kompilierten Bytecode im shared Memory und reduziert den PHP-Overhead dramatisch. Das Problem in der Entwicklung: Wenn OPcache aktiv ist, sieht Magento Code-Änderungen nicht sofort, weil der Cache noch die alte Version hält.
Die Lösung für Magento in Docker ist eine entwicklungsspezifische OPcache-Konfiguration, die Revalidation aktiviert. opcache.validate_timestamps=1 zusammen mit opcache.revalidate_freq=0 bewirkt, dass OPcache bei jedem Request prüft, ob eine Datei auf dem Disk neuer ist als der Cache. Das kostet einen stat-Syscall pro Datei, ist aber deutlich schneller als vollständig ohne Cache zu arbeiten. In der Produktion wird validate_timestamps deaktiviert und der Cache nach dem Deploy manuell invalidiert.
# php/conf.d/opcache-dev.ini — OPcache config for Magento development in Docker
[opcache]
; Enable OPcache — essential for Magento performance even in dev
opcache.enable=1
opcache.enable_cli=1
; Memory: Magento needs at least 512 MB for full codebase
opcache.memory_consumption=512
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=130986
; Development mode: revalidate every request (0 = check every time)
opcache.validate_timestamps=1
opcache.revalidate_freq=0
; Disable JIT in development — easier debugging, consistent behavior
opcache.jit=0
# php/conf.d/opcache-prod.ini — OPcache config for production builds
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=512
opcache.interned_strings_buffer=64
opcache.max_accelerated_files=130986
; Production: never revalidate — invalidate manually after deploy
opcache.validate_timestamps=0
; Enable JIT for PHP 8.x — significant throughput improvement
opcache.jit=1255
opcache.jit_buffer_size=256M
5. Generated-Ordner und var-Cache aus dem Sync ausschließen
Der generated-Ordner in Magento in Docker ist einer der größten Performance-Killer, wenn er Teil eines Bind-Mounts ist. Magento generiert hier Interceptor-Klassen, Factory-Klassen und Proxy-Objekte – bei di:compile entstehen Zehntausende kleiner PHP-Dateien. Jede dieser Dateien über einen Bind-Mount zu schreiben und zu lesen bedeutet massiven I/O-Overhead. Das Gleiche gilt für var/cache, var/page_cache und pub/static: Diese Verzeichnisse sind ausschließlich für den Container relevant und sollten nie auf dem Host landen.
Die korrekte Strategie für Magento in Docker besteht darin, diese Verzeichnisse explizit mit eigenen benannten Volumes zu überschreiben, nachdem der Haupt-Quellcode-Mount definiert wurde. In Docker Compose überschreibt ein spezifischerer Volume-Mount einen übergeordneten. Wenn ./src:/var/www/html als Bind-Mount definiert ist und danach magento-generated:/var/www/html/generated als benanntes Volume, werden Lese- und Schreibzugriffe auf generated direkt im Container-Dateisystem bedient – ohne den Host zu berühren.
6. Hyvä CSS-Watcher im Container betreiben
Der Hyvä-Tailwind-Watcher beobachtet Änderungen in Template-Dateien und baut das CSS neu, sobald sich eine Datei ändert. In einem Magento in Docker-Setup mit Mutagen-Sync funktioniert das reibungslos: Der Watcher läuft als eigenständiger Prozess im Container, beobachtet das Dateisystem innerhalb des Containers und reagiert auf Änderungen, die Mutagen von Host synchronisiert hat. Der Watcher-Prozess selbst benötigt keinen eigenen Bind-Mount für die Template-Dateien, sofern Mutagen den app/design-Ordner zuverlässig synchronisiert.
Für Magento in Docker empfiehlt sich ein separater Compose-Service für den Watcher, der beim Start von bin/start automatisch hochgefahren wird. Der Watcher-Service teilt sich das Magento-Volume mit dem PHP-FPM-Container und führt das npm-Build-Skript aus. Da der Prozess keine eingehenden Verbindungen braucht, braucht er keinen Port und kann mit geringen Ressourcen betrieben werden. Ein restart: unless-stopped stellt sicher, dass der Watcher nach einem Absturz automatisch neu startet.
# compose.dev.yaml — Hyvä CSS watcher as dedicated service
services:
hyva-watcher:
build:
context: .
target: node-watcher
volumes:
# Share the same source volume as phpfpm
- magento-src:/var/www/html
# Bind-mount only the theme being developed
- ./src/app/design:/var/www/html/app/design:delegated
working_dir: /var/www/html/app/design/frontend/Mironsoft/default/web/tailwind
command: npm run watch
restart: unless-stopped
environment:
# Disable polling — use native inotify inside container
CHOKIDAR_USEPOLLING: "0"
depends_on:
- phpfpm
# Dockerfile target for the watcher
# FROM node:20-alpine AS node-watcher
# RUN apk add --no-cache inotify-tools
# WORKDIR /var/www/html
7. Entwicklungs-Compose-Override optimal aufbauen
Ein gut strukturierter Compose-Override für Magento in Docker trennt produktionsrelevante Konfiguration von entwicklungsspezifischen Anpassungen. Die compose.yaml definiert die Basis-Infrastruktur mit benannten Volumes, Netzwerken und Services ohne Entwicklungs-Extras. Die compose.dev.yaml überschreibt nur das, was in der Entwicklung anders sein muss: Bind-Mounts für aktive Entwicklungsverzeichnisse, die Xdebug-PHP-Konfiguration, den Hyvä-Watcher-Service und entspanntere Ressourcenlimits. Dieses Override-Muster ermöglicht, mit docker compose -f compose.yaml -f compose.dev.yaml up eine vollständige Entwicklungsumgebung zu starten.
Für Magento in Docker mit Mark-Shust-Setup übernimmt das Wrapper-Skript bin/start das korrekte Aufrufen der Compose-Dateien, sodass Entwickler nicht jedes Mal die lange Compose-Befehlskette eingeben müssen. Wichtig: Die Reihenfolge der Volume-Definitionen im Override ist entscheidend. Docker verarbeitet sie von oben nach unten, wobei spätere Einträge frühere für denselben Container-Pfad überschreiben. Das ist die Grundlage dafür, dass generated und var in benannte Volumes umgeleitet werden, während der Rest des Quellcodes als Bind-Mount verfügbar bleibt.
8. Xdebug und OPcache im Entwicklungsmodus kombinieren
Xdebug und OPcache schließen sich nicht gegenseitig aus, auch wenn das oft angenommen wird. Für Magento in Docker ist die empfohlene Konfiguration: OPcache immer aktiv mit validate_timestamps=1 und Xdebug im develop-Modus, der var_dump-Ausgaben verbessert, aber keinen Debugger-Overhead erzeugt. Nur wenn aktiv mit dem Debugger gearbeitet wird, schaltet man Xdebug auf den debug-Modus – über eine Umgebungsvariable, die ohne Container-Neustart gesetzt werden kann.
Das Mark-Shust-Setup bietet das Wrapper-Skript bin/xdebug enable|disable, das den Xdebug-Modus im laufenden Container schaltet. Intern schreibt es die Xdebug-Konfigurationsdatei und startet PHP-FPM neu. In diesem Moment kann auch OPcache kurz geleert werden (bin/magento cache:flush), damit der erste Request nach dem Debugger-Aktivieren nicht an veralteten Cache-Einträgen scheitert. Diese Kombination erlaubt, Magento in Docker mit normaler Geschwindigkeit zu entwickeln und den Debugger nur bei Bedarf zuzuschalten.
9. Volume-Strategien im direkten Vergleich
Die Wahl der Volume-Strategie beeinflusst bei Magento in Docker sowohl die Entwicklungsgeschwindigkeit als auch die Komplexität des Setups. Die folgende Tabelle zeigt die wichtigsten Ansätze und ihre Vor- und Nachteile.
| Strategie | I/O-Speed | Komplexität | Empfehlung |
|---|---|---|---|
| Vollständiger Bind-Mount | Langsam (macOS/Win) | Minimal | Nur Linux-Host |
| Delegated Bind-Mount | Moderat | Gering | macOS ohne Mutagen |
| Mutagen + benannte Volumes | Nativ | Mittel | Empfohlen für Magento |
| tmpfs für var/cache | Maximal | Gering | Immer für Cache-Dirs |
| Hybride Strategie | Nativ für kritische Pfade | Mittel | Beste Gesamtlösung |
Auf Linux-Hosts entfällt das I/O-Problem vollständig, da Docker dort direkt auf dem nativen Dateisystem operiert. Auf macOS und Windows ist Mutagen die entscheidende Verbesserung. Die hybride Strategie – benannte Volumes für den Quellcode-Hauptteil, Bind-Mounts nur für aktive Entwicklungsverzeichnisse, tmpfs für Cache-Hot-Paths – liefert in der Praxis das beste Ergebnis für Magento in Docker.
Mironsoft
Magento-Docker-Performance, Hyvä-Entwicklung und DevOps-Infrastruktur
Magento in Docker zu langsam?
Wir analysieren euer Docker-Setup, identifizieren Performance-Bottlenecks bei Volumes und OPcache und implementieren eine hybride Volume-Strategie, die Magento im Container nativ schnell macht.
Performance-Audit
Volume-Strategie, OPcache-Konfiguration und Sync-Setup analysieren und optimieren
Mutagen-Setup
Mutagen-Integration in bestehende Mark-Shust-Setups einrichten und konfigurieren
Hyvä-Integration
CSS-Watcher, Tailwind-Build und Hyvä-Entwicklungsworkflow im Container optimieren
10. Zusammenfassung
Magento in Docker zu beschleunigen ist keine einzelne Maßnahme, sondern eine Kombination aus gezielten Verbesserungen an verschiedenen Stellen. Die Volume-Strategie ist der wichtigste Hebel: Bind-Mounts für kritische Pfade wie generated und var/cache durch benannte Volumes oder tmpfs ersetzen, Mutagen für den Quellcode-Sync einsetzen und nur aktiv bearbeitete Verzeichnisse als Bind-Mount exponieren. OPcache mit validate_timestamps=1 und revalidate_freq=0 hält den PHP-Overhead minimal, ohne Code-Änderungen zu verstecken.
Der Hyvä-Watcher läuft als eigener Service im Container und profitiert direkt von Mutagens schnellem Sync. Xdebug bleibt im develop-Modus, bis aktives Debugging erforderlich ist. Das Ergebnis ist eine Magento in Docker-Umgebung, die sich in der täglichen Entwicklungsarbeit nicht mehr nach einem langsamen Container anfühlt, sondern wie eine native Installation – mit allen Vorteilen der Containerisierung wie Isolierung, Reproduzierbarkeit und einfachem Onboarding.
Magento in Docker beschleunigen — Das Wichtigste auf einen Blick
Volume-Strategie
Benannte Volumes für Quellcode, tmpfs für var/cache und generated. Bind-Mounts nur für aktiv bearbeitete Verzeichnisse wie app/code und app/design.
Mutagen-Sync
Asynchroner Datei-Sync zwischen Host und Container-Volume. Zehntausende Magento-Dateien ohne den macOS-Bind-Mount-Overhead synchron halten.
OPcache-Konfiguration
validate_timestamps=1 + revalidate_freq=0 in der Entwicklung. Mindestspeicher 512 MB, max_accelerated_files auf 130986 für Magento-Codebase.
Hyvä-Watcher
Eigener Compose-Service mit restart: unless-stopped. CHOKIDAR_USEPOLLING deaktiviert, damit inotify im Container nativ reagiert.