Netzwerk, Datenbank und Caches sauber trennen
Wer mehrere Magento Stores für verschiedene Kunden oder Marken betreibt, steht vor der Frage, ob jeder Shop einen eigenen Compose Stack braucht oder ob ein gemeinsamer Stack mit klar getrennten Netzwerken, Datenbank-Schemas und Caches genügt. Dieser Artikel zeigt, wie ein einziger Docker Compose Stack mehrere Magento Stores zuverlässig isoliert, ohne dass Ressourcen mehrfach vorgehalten werden müssen.
Inhaltsverzeichnis
- 1. Warum ein Compose Stack für mehrere Magento Stores
- 2. Architektur-Entscheidung: eine Codebase oder mehrere
- 3. Netzwerk und Domain-Routing pro Store
- 4. Datenbank-Strategie: Schemas statt Container-Wildwuchs
- 5. Shared Services: Redis, OpenSearch und Varnish pro Store aufteilen
- 6. Environment-Variablen sauber pro Store organisieren
- 7. Media-Storage und Volumes zwischen Stores trennen
- 8. Deployment-Overrides für CI/CD mit mehreren Stores
- 9. Isolierte vs. geteilte Stack-Patterns im Vergleich
- 10. Zusammenfassung
- 11. FAQ
1. Warum ein Compose Stack für mehrere Magento Stores
Agenturen und interne Teams betreuen selten nur einen einzigen Shop. Sobald ein zweiter, dritter oder zehnter Kunde dazukommt, stellt sich die Frage, wie mehrere Magento Stores lokal und auf Staging-Servern parallel laufen sollen. Die naive Lösung, für jeden Store einen komplett eigenen Compose Stack mit eigenem PHP-FPM, eigener Datenbank, eigenem Redis und eigenem OpenSearch zu starten, funktioniert bei zwei Shops noch. Bei zehn oder zwanzig Magento Stores auf demselben Entwickler-Rechner oder demselben Staging-Server stößt dieser Ansatz an Speicher- und Portgrenzen.
Ein gemeinsamer Compose Stack für mehrere Magento Stores löst dieses Problem, indem er Basisdienste bündelt und nur dort dupliziert, wo echte Isolation nötig ist. Das Ergebnis ist ein Stack, der zehn Shops mit denselben Ressourcen betreibt, die früher für drei ausgereicht haben. Wichtig ist dabei, klar zwischen Diensten zu unterscheiden, die pro Store isoliert sein müssen, und solchen, die problemlos geteilt werden können.
Dieser Artikel geht Schritt für Schritt durch die Architektur-Entscheidungen, die einen stabilen Docker Compose Stack für mehrere Magento Stores ausmachen: von der Netzwerk-Topologie über Datenbank-Schemas bis zu Deployment-Overrides für CI/CD-Pipelines.
2. Architektur-Entscheidung: eine Codebase oder mehrere
Bevor der Compose Stack entsteht, muss geklärt sein, ob die Magento Stores dieselbe Codebase mit mehreren Website- und Store-View-Konfigurationen nutzen, oder ob es sich um vollständig getrennte Magento-Installationen für verschiedene Kunden handelt. Das ist keine reine Docker-Frage, bestimmt aber maßgeblich, wie der Compose Stack aussieht. Eine einzelne Codebase mit mehreren Websites teilt sich in Magento meist auch eine Datenbank und einen PHP-FPM-Container, weil die Store-View-Trennung bereits auf Applikationsebene passiert.
Bei getrennten Kunden-Installationen, wie es bei Agentur-Setups üblich ist, braucht jeder Store dagegen einen eigenen PHP-FPM-Container mit eigenem Codebase-Mount, weil Magento-Versionen, Module und Customizations pro Kunde unterschiedlich sind. Der Compose Stack definiert für diesen Fall einen Service-Block pro Kunden-Store, verwendet aber dieselben Basis-Images und dieselben Shared Services für Infrastruktur-Komponenten, die keine kundenspezifische Logik enthalten.
In der Praxis hat sich ein Hybrid-Ansatz bewährt: Jeder Magento Store bekommt einen eigenen PHP-FPM-Container und einen eigenen Nginx-Vhost, teilt sich aber MySQL, Redis und OpenSearch als Multi-Tenant-Dienste mit logischer Trennung auf Schema- beziehungsweise Index-Ebene. Diese Aufteilung reduziert den Ressourcenverbrauch drastisch, ohne die Store-Isolation zu gefährden.
3. Netzwerk und Domain-Routing pro Store
Der kritischste Teil eines Compose Stacks mit mehreren Magento Stores ist das Routing eingehender Requests zum richtigen PHP-FPM-Container. Ein Reverse Proxy wie Traefik oder nginx-proxy übernimmt diese Aufgabe, indem er Requests anhand des Hostnamens an das passende Backend weiterleitet. Jeder Store bekommt dabei eine eigene lokale Domain, zum Beispiel shop-a.test, shop-b.test und shop-c.test, die per Labels am jeweiligen Service deklariert wird.
Traefik liest diese Labels automatisch aus dem Docker-Socket und baut daraus die Routing-Regeln, ohne dass eine zentrale Konfigurationsdatei bei jedem neuen Store manuell angepasst werden muss. Das ist der entscheidende Vorteil gegenüber einer klassischen Nginx-Konfiguration mit statischen Server-Blöcken: Ein neuer Magento Store wird einfach als weiterer Service mit passenden Labels ergänzt, und der Proxy erkennt ihn beim nächsten Start automatisch.
# docker-compose.yml — multiple Magento stores behind Traefik
services:
traefik:
image: traefik:v3.1
command:
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
networks:
- proxy
magento-shop-a:
build: ./stores/shop-a
environment:
MAGENTO_RUN_CODE: shop_a_store
DB_HOST: mysql
DB_NAME: shop_a
labels:
- "traefik.enable=true"
- "traefik.http.routers.shop-a.rule=Host(`shop-a.test`)"
- "traefik.http.services.shop-a.loadbalancer.server.port=8080"
networks:
- proxy
- backend
magento-shop-b:
build: ./stores/shop-b
environment:
MAGENTO_RUN_CODE: shop_b_store
DB_HOST: mysql
DB_NAME: shop_b
labels:
- "traefik.enable=true"
- "traefik.http.routers.shop-b.rule=Host(`shop-b.test`)"
- "traefik.http.services.shop-b.loadbalancer.server.port=8080"
networks:
- proxy
- backend
networks:
proxy:
backend:
Diese Struktur skaliert linear: Jeder weitere Magento Store ist ein zusätzlicher Service-Block mit eigenen Labels, ohne dass Traefik selbst angefasst werden muss. Wichtig ist, ein separates backend-Netzwerk zu verwenden, damit die PHP-FPM-Container untereinander und mit MySQL kommunizieren können, während nur Traefik im proxy-Netzwerk direkt erreichbar ist. Das reduziert die Angriffsfläche gegenüber einer flachen Netzwerktopologie erheblich.
4. Datenbank-Strategie: Schemas statt Container-Wildwuchs
Ein häufiger Anfängerfehler bei Magento Stores in Compose ist, für jeden Shop einen eigenen MySQL-Container zu starten. Das kostet unnötig Arbeitsspeicher, weil jede MySQL-Instanz ihren eigenen Buffer Pool, eigene Connection-Handler und eigene InnoDB-Strukturen mitbringt. Der bessere Weg ist ein einziger MySQL-Container mit einem eigenen Schema pro Store. Magento unterstützt das nativ über die DB_NAME-Umgebungsvariable pro Installation, und MySQL selbst ist für Dutzende Schemas in einer Instanz ausgelegt.
Wichtig ist dabei, für jeden Magento Store einen eigenen Datenbank-User mit Rechten ausschließlich auf das eigene Schema anzulegen. Ein gemeinsamer Root-User über alle Stores hinweg wäre ein Sicherheitsrisiko, weil ein kompromittierter Store dann auch Zugriff auf die Daten aller anderen Shops hätte. Die Schema-Trennung mit granularen Rechten hält die Isolation auch bei einem gemeinsam genutzten Datenbank-Container aufrecht.
#!/usr/bin/env bash
# init-multi-store-db.sh — one schema and user per Magento store
set -euo pipefail
STORES=("shop_a" "shop_b" "shop_c")
for store in "${STORES[@]}"; do
mysql -h mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" <<SQL
CREATE DATABASE IF NOT EXISTS \`${store}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER IF NOT EXISTS '${store}_user'@'%' IDENTIFIED BY '${store}_pass';
GRANT ALL PRIVILEGES ON \`${store}\`.* TO '${store}_user'@'%';
SQL
echo "[OK] Schema and user provisioned for ${store}"
done
mysql -h mysql -uroot -p"${MYSQL_ROOT_PASSWORD}" -e "FLUSH PRIVILEGES;"
5. Shared Services: Redis, OpenSearch und Varnish pro Store aufteilen
Redis kennt logische Datenbanken über den Index 0 bis 15, was sich anbietet, um pro Magento Store Cache und Session getrennt zu halten, ohne einen zusätzlichen Container zu starten. Ein Store nutzt Redis-DB 0 für Cache und DB 1 für Sessions, der nächste Store DB 2 und 3, und so weiter. Diese Trennung verhindert, dass ein Cache-Flush in einem Store versehentlich die Sessions eines anderen Stores mitreißt.
Bei OpenSearch ist die Trennung noch einfacher, weil Magento pro Store ohnehin einen eigenen Index-Präfix verwendet. Ein einziger OpenSearch-Container reicht für zehn Magento Stores problemlos aus, solange die Indexnamen über die Konfiguration OPENSEARCH_INDEX_PREFIX pro Store eindeutig gesetzt werden. Varnish hingegen braucht pro Store eine eigene VCL-Konfiguration, weil Cache-Invalidierung, Backend-Definition und Hostname-Zuordnung storespezifisch sind, aber ein einzelner Varnish-Container kann mehrere Backends über vcl_recv anhand des Hosts unterscheiden.
Die grundsätzliche Regel für Magento Stores in einem gemeinsamen Stack lautet: Dienste mit eingebauter Multi-Tenant-Fähigkeit (Redis-DBs, OpenSearch-Indizes, MySQL-Schemas) werden geteilt, Dienste ohne diese Fähigkeit (PHP-FPM wegen unterschiedlicher Codebases, Varnish-VCL wegen unterschiedlicher Backend-Logik) werden pro Store oder mit interner Logik dediziert konfiguriert.
6. Environment-Variablen sauber pro Store organisieren
Mit wachsender Anzahl an Magento Stores im selben Compose Stack wird die Verwaltung der Umgebungsvariablen schnell unübersichtlich, wenn alles in einer einzigen .env-Datei landet. Der bessere Ansatz ist eine .env-Datei pro Store, die über env_file im jeweiligen Service-Block eingebunden wird. Das hält Konfigurationswerte pro Shop isoliert und macht Diffs bei Änderungen an einem einzelnen Store übersichtlich.
Zusätzlich empfiehlt sich ein Namensschema mit Store-Präfix für alle store-spezifischen Variablen, etwa SHOP_A_DB_NAME oder SHOP_A_REDIS_DB, sobald Werte aus mehreren .env-Dateien in einer übergeordneten Compose-Datei zusammenlaufen. Das verhindert Namenskollisionen, wenn zwei Magento Stores zufällig dieselbe generische Variable wie DB_NAME in unterschiedlichem Kontext erwarten.
7. Media-Storage und Volumes zwischen Stores trennen
Jeder Magento Store braucht ein eigenes Volume für pub/media, var/log und var/cache, selbst wenn PHP-FPM-Container aus demselben Image gebaut werden. Ein gemeinsames Volume für mehrere Stores würde dazu führen, dass hochgeladene Produktbilder eines Shops im Verzeichnis eines anderen Shops landen, sobald beide Container denselben Mount-Pfad verwenden. Named Volumes mit Store-Präfix im Namen, etwa shop_a_media und shop_b_media, schaffen hier klare Grenzen.
Für Backups mehrerer Magento Stores in einem Stack lohnt sich ein zentrales Backup-Skript, das über alle Store-Volumes iteriert und pro Store ein eigenes Archiv erzeugt. So bleibt der Restore-Prozess für einen einzelnen Shop isoliert möglich, ohne den kompletten Stack aus einem gemeinsamen Backup wiederherstellen zu müssen. Das ist besonders bei Agentur-Setups wichtig, in denen einzelne Kunden gelegentlich einen Rollback auf einen älteren Stand benötigen, während die anderen Stores unverändert weiterlaufen sollen.
8. Deployment-Overrides für CI/CD mit mehreren Stores
Für den produktiven Betrieb mehrerer Magento Stores aus demselben Compose-Setup empfiehlt sich eine Basis-Compose-Datei mit gemeinsamen Definitionen und ein Override pro Umgebung, der store-spezifische Werte wie Domain, Ressourcenlimits und Replikenanzahl überschreibt. So bleibt die Grundstruktur für lokale Entwicklung, Staging und Produktion identisch, während sich nur die Parameter pro Umgebung und Store unterscheiden.
# docker-compose.prod.yml — production override for multiple Magento stores
services:
magento-shop-a:
deploy:
resources:
limits:
cpus: "2.0"
memory: 1536M
environment:
MAGE_MODE: production
REDIS_CACHE_DB: "0"
REDIS_SESSION_DB: "1"
magento-shop-b:
deploy:
resources:
limits:
cpus: "1.0"
memory: 1024M
environment:
MAGE_MODE: production
REDIS_CACHE_DB: "2"
REDIS_SESSION_DB: "3"
In der CI/CD-Pipeline lässt sich dieses Muster nutzen, um gezielt nur den betroffenen Magento Store neu zu deployen, statt bei jeder Codeänderung den kompletten Stack neu zu starten. Ein Deployment-Skript, das den geänderten Store aus dem Git-Diff ermittelt und nur dessen Compose-Service neu baut und neu startet, hält Deployments kurz und reduziert Downtime für die unbeteiligten Shops auf null.
9. Isolierte vs. geteilte Stack-Patterns im Vergleich
Die Entscheidung, welche Komponente pro Store isoliert und welche geteilt wird, hat direkte Auswirkungen auf Ressourcenverbrauch und Betriebssicherheit. Die folgende Übersicht fasst die empfohlenen Patterns für Magento Stores in einem gemeinsamen Compose Stack zusammen.
| Komponente | Isoliert pro Store | Geteilt mit Trennung | Empfehlung |
|---|---|---|---|
| PHP-FPM | Eigener Container | Nicht sinnvoll | Isolieren, unterschiedliche Codebases |
| MySQL | Nur bei starker Isolation nötig | Ein Container, ein Schema pro Store | Teilen, Schema-Trennung reicht |
| Redis | Selten nötig | Logische DBs pro Store | Teilen, DB-Index-Trennung |
| OpenSearch | Nur bei sehr großen Indizes | Index-Präfix pro Store | Teilen, Präfix-Trennung |
| Varnish | Möglich, aber aufwändig | Eine Instanz, VCL nach Host | Teilen mit Host-basierter VCL |
| Media-Volume | Eigenes Named Volume | Nicht sinnvoll | Isolieren, verhindert Datei-Kollisionen |
In der Praxis zeigt sich, dass die größten Einsparungen bei MySQL, Redis und OpenSearch entstehen, weil diese Dienste ohnehin für Multi-Tenant-Betrieb ausgelegt sind. PHP-FPM und Media-Volumes bleiben dagegen isoliert, weil dort echte Codebase- und Datei-Trennung nötig ist. Diese Kombination erlaubt es, zehn oder mehr Magento Stores mit dem Ressourcenbedarf zu betreiben, den früher drei separate Stacks benötigt hätten.
Mironsoft
Magento Docker Infrastruktur und Multi-Store-Betrieb
Mehrere Magento Stores, ein sauberer Compose Stack?
Wir entwerfen Multi-Store-Architekturen für Agenturen und Inhouse-Teams, die Ressourcen bündeln, ohne Isolation und Sicherheit zu opfern, inklusive Netzwerk, Datenbank-Trennung und Deployment-Automatisierung.
Architektur-Review
Bestehende Multi-Store-Setups analysieren und Ressourcenverschwendung aufdecken
Compose-Refactoring
Von einem Stack pro Shop zu einem konsolidierten, sicheren Multi-Store-Stack
CI/CD-Automatisierung
Selektive Deployments pro Store ohne Downtime für die restlichen Shops
10. Zusammenfassung
Mehrere Magento Stores in einem einzigen Docker Compose Stack zu betreiben, ist keine exotische Konfiguration, sondern der wirtschaftlich sinnvolle Standardweg für Agenturen und Teams mit mehr als ein oder zwei Shops. Der Schlüssel liegt darin, Dienste mit eingebauter Multi-Tenant-Fähigkeit wie MySQL, Redis und OpenSearch zu teilen und nur dort zu isolieren, wo echte Codebase- oder Datei-Trennung nötig ist, also bei PHP-FPM und Media-Volumes.
Ein Reverse Proxy mit Label-basiertem Routing macht das Hinzufügen neuer Magento Stores zu einer reinen Konfigurationsaufgabe ohne manuellen Eingriff in zentrale Proxy-Configs. Kombiniert mit store-spezifischen .env-Dateien, Schema-Trennung in MySQL und Named Volumes pro Store entsteht ein Stack, der zehn oder mehr Shops mit dem Ressourcenbedarf betreibt, den früher drei separate Stacks benötigt hätten, ohne die Sicherheit einzelner Stores zu gefährden.
Mehrere Magento Stores in einem Compose Stack — Das Wichtigste auf einen Blick
Netzwerk
Reverse Proxy mit Label-Routing pro Store, eigenes Backend-Netzwerk pro Trust-Zone.
Datenbank
Ein MySQL-Container, ein Schema und ein User pro Store, granulare Rechte statt Root-Zugriff.
Caches
Redis-DB-Index und OpenSearch-Präfix pro Store, ein Container für alle Shops.
Storage
Eigenes Named Volume pro Store für Media, Logs und Cache, verhindert Datei-Kollisionen.