PHP-FPM, Nginx, Node, Elasticsearch und DB
Magento 2 braucht einen präzise abgestimmten Service-Stack. PHP-FPM, Nginx, MariaDB, Redis, Elasticsearch oder OpenSearch und einen Node-Container für Frontend-Builds – jeder dieser Services hat spezifische Konfigurationsanforderungen, die in Docker nicht identisch zur klassischen Server-Installation sind. Wer diese Unterschiede kennt, baut einen stabilen und performanten Magento-Docker-Stack.
Inhaltsverzeichnis
- 1. Der Magento-Stack: Warum so viele Services
- 2. PHP-FPM richtig konfigurieren
- 3. Nginx als Magento-Frontend-Proxy
- 4. MariaDB: Performance und Healthcheck
- 5. Redis: Session und Full Page Cache
- 6. Elasticsearch und OpenSearch: Catalog Search
- 7. Node.js für Hyvä Tailwind Builds
- 8. Volume-Strategie für Magento
- 9. Konfigurationsvarianten im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Der Magento-Stack: Warum so viele Services
Docker für Magento erfordert mehr Services als eine typische PHP-Anwendung. Magento 2.4 läuft nicht ohne eine Suchmaschine – Elasticsearch oder OpenSearch ist Pflicht für den Catalog Search. Redis ist zwar technisch optional, aber in der Praxis unverzichtbar für Session-Speicher und den Full Page Cache: ohne Redis skaliert Magento auch bei moderatem Traffic nicht. MariaDB oder MySQL ist der primäre Datenspeicher. PHP-FPM verarbeitet Requests hinter Nginx. Und für Hyvä-Themes braucht man einen Node-Container, der Tailwind CSS kompiliert. Der vollständige Stack umfasst damit mindestens sechs Container.
Der wichtigste Grundsatz beim Docker-Magento-Setup: jeder Service ist für genau eine Aufgabe zuständig. PHP-FPM verarbeitet PHP, Nginx liefert statische Dateien direkt aus und proxied PHP-Requests. MariaDB speichert Daten, Redis cached. Diese Trennung ermöglicht es, jeden Service unabhängig zu skalieren und zu konfigurieren. Der häufigste Fehler ist ein kombinierter PHP+Nginx-Container – der verhindert unabhängige Skalierung und macht Health-Checks schwieriger. Mit Docker für Magento lässt sich die Trennung konsequent durchsetzen.
2. PHP-FPM richtig konfigurieren
PHP-FPM im Docker-Magento-Setup benötigt eine spezifische Konfiguration, die sich von der Standard-Debian/Ubuntu-Installation unterscheidet. Der PHP-FPM-Container muss auf Port 9000 oder via Unix-Socket hören – in Docker ist der TCP-Port einfacher, weil Socket-Dateien über gemeinsame Volumes geteilt werden müssen. Die wichtigsten PHP-Einstellungen für Magento sind: memory_limit mindestens 2G für Magento-Operationen wie setup:di:compile, max_execution_time mindestens 1800 für lange CLI-Prozesse und opcache muss aktiviert und für Production korrekt dimensioniert sein.
Für Hyvä-Themes mit Docker für Magento und PHP 8.4 sind zusätzliche Extensions nötig: bcmath, gd, intl, pdo_mysql, soap, xsl und zip. Diese Extensions müssen im Dockerfile des PHP-FPM-Images installiert sein. Der Mark Shust Docker-Magento-Stack nutzt ein vorkonfiguriertes Image, das alle Magento-Extensions enthält – für eigene Images empfiehlt sich dasselbe als Basis. Xdebug gehört nur ins Entwicklungs-Image und sollte per Override aktiv geschaltet werden, nicht in der Basis-Konfiguration.
# Docker Compose service definitions for a complete Magento 2 stack
# Each service has a single responsibility — PHP processes PHP, Nginx serves static files
services:
phpfpm:
image: markoshust/magento-php:8.4-fpm-0
networks: [magento]
volumes:
- magento_src:/var/www/html # shared source volume
- ./src/app/etc/php.ini.sample:/usr/local/etc/php/conf.d/99-magento.ini:ro
environment:
MAGENTO_RUN_MODE: production
PHP_MEMORY_LIMIT: 2G
PHP_MAX_EXECUTION_TIME: 1800
PHP_OPCACHE_ENABLE: 1
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
opensearch:
condition: service_healthy
restart: unless-stopped
nginx:
image: markoshust/magento-nginx:1.24-0
networks: [magento]
ports:
- "80:8000"
- "443:8443"
volumes:
- magento_src:/var/www/html:ro # read-only for static file serving
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- phpfpm
restart: unless-stopped
# CLI container for Magento commands — same image as phpfpm, different purpose
cli:
image: markoshust/magento-php:8.4-fpm-0
networks: [magento]
volumes:
- magento_src:/var/www/html
command: ["tail", "-f", "/dev/null"] # keep container running for exec
profiles: [cli] # only start when explicitly needed
3. Nginx als Magento-Frontend-Proxy
Nginx im Docker-Magento-Setup hat zwei Aufgaben: statische Dateien direkt aus dem Dateisystem ausliefern und PHP-Requests an PHP-FPM weiterleiten. Die Nginx-Konfiguration für Magento ist komplex – Magento liefert eine offizielle nginx.conf.sample, die als Ausgangspunkt dient. Die wichtigsten Anpassungen für Docker für Magento: das fastcgi_pass-Directive muss auf den PHP-FPM-Container-Namen zeigen (phpfpm:9000 statt eines Unix-Sockets), und der root-Pfad muss mit dem Volume-Mount-Pfad übereinstimmen.
Ein häufiger Fehler im Docker-Magento-Nginx-Setup: das statische Content-Verzeichnis /pub/static ist nicht im Nginx-Container vorhanden, weil nur PHP-FPM Zugriff auf das Source-Volume hat. Die Lösung ist, das gemeinsame Volume sowohl in PHP-FPM als auch in Nginx zu mounten – in Nginx read-only, in PHP-FPM read-write. Das erfordert ein benanntes Docker-Volume statt eines Host-Pfad-Mounts, damit beide Container auf denselben Dateistand zugreifen. Gzip-Kompression für JS, CSS und HTML sollte in der Nginx-Konfiguration aktiviert sein – das reduziert die übertragene Datenmenge bei Hyvä-Themes erheblich.
4. MariaDB: Performance und Healthcheck
MariaDB im Docker-Magento-Stack braucht eine spezifische Konfiguration, die über das Standard-Image hinausgeht. Die wichtigsten InnoDB-Parameter für Magento: innodb_buffer_pool_size sollte 70–80% des verfügbaren RAM betragen, innodb_log_file_size mindestens 256M, max_allowed_packet mindestens 64M für große Magento-Importe. Diese Werte als Umgebungsvariablen oder als Custom-Config-Datei via Volume-Mount zu übergeben, ist besser als das Image zu erweitern – so bleiben Updates einfach.
Der Healthcheck für MariaDB in Docker für Magento ist entscheidend, weil PHP-FPM und Nginx erst dann starten sollten, wenn die Datenbank bereit ist. Der offizielle MariaDB-Container enthält ein healthcheck.sh-Script, das genau dafür gedacht ist. Mit depends_on: condition: service_healthy in PHP-FPM und anderen Services, die die Datenbank benötigen, wird sichergestellt, dass der Startup-Reihenfolge korrekt eingehalten wird. Ohne diesen Mechanismus starten Services parallel und schlagen fehl, wenn die Datenbank noch initialisiert wird.
# Database and caching services for Docker Magento
# MariaDB with performance tuning, Redis for two separate roles
db:
image: mariadb:11.4
networks: [magento]
volumes:
- db_data:/var/lib/mysql
- ./mysql/conf.d:/etc/mysql/conf.d:ro # custom InnoDB config
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MYSQL_DATABASE: magento
MYSQL_USER: magento
MYSQL_PASSWORD: ${DB_PASSWORD}
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
restart: unless-stopped
# mysql/conf.d/magento.cnf — InnoDB tuning for Magento workloads
# [mysqld]
# innodb_buffer_pool_size = 2G
# innodb_log_file_size = 256M
# max_allowed_packet = 64M
# innodb_flush_log_at_trx_commit = 2 # faster, slight durability trade-off
redis:
image: redis:7-alpine
networks: [magento]
command: ["redis-server", "--maxmemory", "512mb", "--maxmemory-policy", "allkeys-lru"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
restart: unless-stopped
# Separate Redis instance for session storage (isolated from page cache)
redis-session:
image: redis:7-alpine
networks: [magento]
command: ["redis-server", "--maxmemory", "256mb", "--maxmemory-policy", "noeviction"]
restart: unless-stopped
5. Redis: Session und Full Page Cache
Redis im Docker-Magento-Setup erfüllt zwei verschiedene Rollen: Full Page Cache und Session-Speicher. Diese beiden Anwendungsfälle haben unterschiedliche Eviction-Policies und sollten idealerweise getrennte Instanzen nutzen. Für den Full Page Cache ist allkeys-lru korrekt – alte Seiten werden verdrängt, wenn der Speicher voll ist. Für Sessions ist noeviction richtig – Sessions dürfen niemals automatisch gelöscht werden, weil das zu unerwarteten Logouts führt. Zwei separate Redis-Container in Docker für Magento sind einfach zu konfigurieren und vermeiden dieses Problem vollständig.
Magento 2.4 nutzt Redis über die env.php-Konfiguration. In einem Docker-Magento-Setup sollten die Redis-Hosts auf die Compose-Service-Namen zeigen: 'host' => 'redis' für den Page-Cache und 'host' => 'redis-session' für Sessions. Wichtig: Redis persistiert Daten standardmäßig nicht. Für Produktionsumgebungen sollte redis.conf mit appendonly yes und einem Volume für das AOF-File konfiguriert werden. In der Entwicklung ist Persistenz optional – ein Redis-Neustart ist schnell, und der Cache wird automatisch neu aufgebaut.
6. Elasticsearch und OpenSearch: Catalog Search
Elasticsearch oder OpenSearch im Docker-Magento-Stack ist der ressourcenhungrigste Service. Elasticsearch benötigt mindestens 1 GB Heap, OpenSearch mindestens 512 MB. Der häufigste Fehler ist die fehlende Einstellung vm.max_map_count auf dem Host: Elasticsearch bricht mit einem OutOfMemoryError ab, wenn dieser Kernel-Parameter nicht auf mindestens 262144 gesetzt ist. In Docker Desktop auf macOS und Windows wird dieser Wert automatisch gesetzt, auf Linux-Hosts muss er manuell gesetzt werden: sysctl -w vm.max_map_count=262144.
Magento 2.4.8 unterstützt OpenSearch 2.x als bevorzugte Alternative zu Elasticsearch 7. Der Docker-Magento-Stack sollte OpenSearch nutzen, da Elasticsearch 7 das EOL-Datum überschritten hat. Die Konfiguration in Magento erfolgt über den Admin unter Stores → Configuration → Catalog Search. Im Docker-Setup ist der Host einfach der Compose-Service-Name (opensearch), der Port 9200. Der Healthcheck für OpenSearch überprüft die Cluster-Health-API – Service-Status green oder yellow ist akzeptabel, red bedeutet, dass Shards fehlen.
# OpenSearch service for Magento 2.4 catalog search
# Elasticsearch has reached EOL — use OpenSearch 2.x instead
opensearch:
image: opensearchproject/opensearch:2.13.0
networks: [magento]
volumes:
- opensearch_data:/usr/share/opensearch/data
environment:
- "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m"
- "discovery.type=single-node"
- "plugins.security.disabled=true" # disable auth for local dev
- "DISABLE_PERFORMANCE_ANALYZER_AGENT_CLI=true"
healthcheck:
test: ["CMD-SHELL", "curl -s -o /dev/null -w '%{http_code}' http://localhost:9200/_cluster/health | grep -qE '200'"]
interval: 15s
timeout: 10s
retries: 10
start_period: 60s
restart: unless-stopped
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
# OpenSearch Dashboards — optional, activate with profile
opensearch-dashboards:
image: opensearchproject/opensearch-dashboards:2.13.0
networks: [magento]
ports:
- "5601:5601"
environment:
- "OPENSEARCH_HOSTS=http://opensearch:9200"
- "DISABLE_SECURITY_DASHBOARDS_PLUGIN=true"
profiles: [monitoring]
7. Node.js für Hyvä Tailwind Builds
Hyvä-Themes in einem Docker-Magento-Setup benötigen Node.js für den Tailwind CSS Build. Das bedeutet: kein Node auf dem Host-System nötig, aber ein Node-Container oder ein Multi-Stage-Build-Setup. Die einfachste Lösung ist ein dedizierter Node-Service in der docker-compose.override.yml, der das Tailwind-Verzeichnis als Volume mountet und mit einem File-Watcher läuft. Entwickler können dann CSS-Änderungen ohne manuelle Build-Schritte direkt im Browser sehen. Der Service nutzt das offizielle Node-Image in der LTS-Version.
Für Produktions-Deploys im Docker-Magento-Stack gehört der Tailwind-Build in den CI/CD-Prozess: ein Multi-Stage-Dockerfile oder ein separater Build-Container baut den CSS-Output und legt ihn in das finale Image. Das stellt sicher, dass das Produktions-Image immer den aktuellen CSS-Build enthält und kein laufender Node-Prozess im Produktions-Container nötig ist. Der Node-Container im Compose-Stack ist ausschließlich für die lokale Entwicklung gedacht und sollte in CI und Produktion nicht gestartet werden – ein Profile wie dev-tools kapselt ihn sauber.
8. Volume-Strategie für Magento
Die Volume-Strategie ist einer der kritischsten Aspekte beim Docker-Magento-Setup. Magento generiert während des Betriebs erhebliche Mengen an Dateien: kompilierter Code unter var/generation, statische Inhalte unter pub/static, Logs unter var/log und Cache unter var/cache. Diese Verzeichnisse sollten auf benannte Docker-Volumes gemappt werden, nicht auf Host-Pfade – das verbessert die I/O-Performance erheblich, besonders auf macOS mit Docker Desktop, wo Host-Mounts notorisch langsam sind.
Die Source-Code-Dateien selbst werden für lokale Entwicklung als Host-Mount eingebunden, damit Änderungen sofort sichtbar sind. Das Muster für einen Docker-Magento-Stack: das Root-Verzeichnis als Host-Mount, die generierten und Cache-Verzeichnisse als benannte Volumes. Dieser Ansatz kombiniert schnelle Iterationszyklen für den Source-Code mit optimaler I/O-Performance für generierte Dateien. In Produktionsumgebungen gibt es keine Host-Mounts – alle Dateien kommen aus dem Image, und nur persistente Daten wie Uploads, DB-Daten und Log-Dateien liegen in Volumes.
9. Konfigurationsvarianten im Vergleich
Beim Aufbau eines Docker-Magento-Stacks gibt es verschiedene Konfigurationsentscheidungen, die die Performance und Wartbarkeit beeinflussen.
| Entscheidung | Option A | Option B (empfohlen) | Begründung |
|---|---|---|---|
| PHP-FPM/Nginx | Ein kombinierter Container | Separate Container | Unabhängige Skalierung, klare Health-Checks |
| Suchmaschine | Elasticsearch 7 (EOL) | OpenSearch 2.x | Magento 2.4.8 offiziell unterstützt |
| Redis | Eine Instanz für alles | Getrennte Instanzen | Verschiedene Eviction-Policies nötig |
| Source-Code-Volumes | Nur Host-Mounts | Host-Mount + Named Volumes für Cache | Performance auf macOS erheblich besser |
| Node/Tailwind | Auf Host installiert | Docker-Container mit Profile | Keine Host-Abhängigkeiten, reproduzierbar |
Die Entscheidung für separate Redis-Instanzen für Session und Cache ist auf den ersten Blick überdimensioniert, zahlt sich aber beim ersten Produktionsproblem aus: eine volle Page-Cache-Instanz verdrängt niemals Sessions, wenn die Instanzen getrennt sind. Das verhindert unerwartete Logouts unter Last – ein Fehler, der in Produktions-Docker-Magento-Stacks regelmäßig auftritt, wenn beide Rollen eine einzige Redis-Instanz teilen.
10. Zusammenfassung
Ein sauberer Docker-Magento-Stack besteht aus mindestens sechs Services mit klarer Aufgabentrennung: PHP-FPM für die Anwendungslogik, Nginx für statische Dateien und Proxy, MariaDB für persistente Daten, zwei Redis-Instanzen für Page-Cache und Session, OpenSearch für die Katalogsuche und optional ein Node-Container für lokale Tailwind-Builds. Jeder Service hat einen Healthcheck, und die Startup-Reihenfolge wird über depends_on mit condition: service_healthy gesteuert.
Die Volume-Strategie ist der häufigste Performance-Engpass in Docker-Magento-Setups: Host-Mounts für Source-Code, benannte Volumes für generierte Dateien und Cache-Verzeichnisse. Auf macOS ist der Unterschied zwischen diesen beiden Ansätzen für Magento-Requests messbar. In Produktionsumgebungen kommen keine Host-Mounts vor – das Image enthält alle Anwendungsdateien, und nur persistente Daten liegen in Volumes. Mit dieser Konfiguration verhält sich der Magento-Stack in jeder Umgebung vorhersehbar.
Mironsoft
Magento 2 Docker-Setup, Hyvä-Entwicklung und Shop-Infrastruktur
Magento-Docker-Stack für euren Shop?
Wir bauen und konfigurieren den vollständigen Docker-Magento-Stack – von PHP-FPM über OpenSearch bis zur Hyvä-Tailwind-Pipeline. Produktion und lokale Entwicklung aus einem Guss.
Stack-Setup
Vollständiger Magento-Docker-Stack mit PHP-FPM, Nginx, MariaDB, Redis und OpenSearch
Performance-Tuning
InnoDB-Konfiguration, Redis-Dimensionierung, OpCache-Einstellungen und Volume-Strategie
Hyvä-Integration
Node-Container für Tailwind-Builds, CI/CD-Pipeline und Multi-Stage-Dockerfiles
Docker für Magento — Das Wichtigste auf einen Blick
Pflicht-Services
PHP-FPM, Nginx, MariaDB, Redis (×2), OpenSearch. Jeder Service mit eigenem Healthcheck und depends_on: condition: service_healthy.
Redis-Strategie
Zwei Instanzen: Page Cache (allkeys-lru) und Session (noeviction). Verhindert unerwartete Logouts unter Last.
Volume-Performance
Source-Code als Host-Mount, generierte Dateien (var/, pub/static) als benannte Volumes. Auf macOS erheblich schneller.
OpenSearch
vm.max_map_count=262144 auf dem Host erforderlich. OpenSearch 2.x statt Elasticsearch 7 (EOL). Einzelner Node für Dev und Staging.
11. FAQ: Docker für Magento
1Warum so viele Services für Magento?
2OpenSearch statt Elasticsearch?
3OpenSearch schlägt beim Start fehl?
vm.max_map_count zu niedrig. Auf Linux: sysctl -w vm.max_map_count=262144. Docker Desktop setzt dies automatisch.4Warum zwei Redis-Instanzen?
allkeys-lru, Sessions brauchen noeviction. Eine Instanz kann Sessions unter Speicherdruck verlieren.5Volume-Performance auf macOS verbessern?
var/, pub/static) als benannte Docker-Volumes – deutlich schneller als Host-Mounts über FUSE.6PHP-FPM memory_limit für Magento?
setup:di:compile). Als Umgebungsvariable oder Custom php.ini.7Node für Hyvä Tailwind Builds?
8Startup-Reihenfolge steuern?
depends_on: condition: service_healthy. Erfordert korrekte Healthchecks auf db, redis und opensearch.