Mehrere Magento Stores in einem Docker Compose Stack betreiben
AI generated
FROM
RUN
Docker · Magento · Compose · Multi-Store
Mehrere Magento Stores in einem Docker Compose Stack betreiben
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.

18 Min. Lesezeit Docker Compose · Multi-Store · Reverse Proxy Magento 2.4.8 · MySQL · Redis · OpenSearch

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.

11. FAQ: Mehrere Magento Stores in einem Compose Stack

1Eigener MySQL-Container pro Store nötig?
Nein, ein Container mit Schema und User pro Store reicht für Dutzende Stores und spart RAM gegenüber mehreren Instanzen.
2Wie routet Traefik zum richtigen Store?
Über Docker-Labels mit Host-Regel am Service, automatisch aus dem Docker-Socket gelesen, kein zentrales Config-File nötig.
3Gemeinsame Redis-Instanz möglich?
Ja, über logische DB-Indizes pro Store für Cache und Session, kein zusätzlicher Container nötig.
4Warum PHP-FPM pro Store isolieren?
Unterschiedliche Codebases, Versionen und Customizations pro Store würden sich in einem gemeinsamen Container vermischen.
5Produktbilder-Vermischung verhindern?
Eigenes Named Volume pro Store für pub/media, kein geteilter Mount-Pfad über mehrere Container.
6Skalierung bei zwanzig Stores?
Linear für geteilte Dienste, Grenze liegt bei CPU und RAM der isolierten PHP-FPM-Container.
7Nur einen Store deployen, andere unberührt?
Deployment-Skript ermittelt geänderten Store aus Git-Diff, baut und startet gezielt nur dessen Service neu.
8Eigene Varnish-Instanz pro Store?
In der Regel nicht nötig, eine Instanz unterscheidet Backends über vcl_recv anhand des Hostnamens.
9Umgebungsvariablen übersichtlich organisieren?
Eigene .env-Datei pro Store über env_file, plus Namensschema mit Store-Präfix bei zusammenlaufenden Variablen.
10Größter Fehler bei Multi-Store-Compose?
Für jeden Store einen kompletten eigenen Stack zu duplizieren, statt Multi-Tenant-fähige Dienste zu teilen.