Wenn ich an einer Shopware-Anbindung oder einem Plugin arbeite, brauche ich einen Shop, den ich ohne schlechtes Gewissen kaputt machen darf. Eine vollständige Installation mit Webserver, PHP, MySQL und Mailserver ist dafür zu viel Aufwand. Deshalb habe ich mir einen kleinen Playground gebaut: eine einzige docker-compose.yml, ein Befehl, und nach kurzer Zeit läuft ein kompletter Shopware-Shop auf meinem Mac.
In diesem Beitrag zeige ich dir, wie das Docker Setup aussieht, welche Zugänge du bekommst und auf welche Stolperfallen du achten solltest.
Was ist dockware?
dockware stellt fertige Docker-Images für Shopware bereit. In einem einzigen Container stecken
- Webserver,
- PHP,
- MySQL,
- ein Mailcatcher
- und eine fertig installierte Shopware-Instanz.
Du musst nichts konfigurieren und nichts installieren. Für die Entwicklung und zum Ausprobieren ist das ideal. Für den Produktivbetrieb ist es ausdrücklich nicht gedacht.
Shopware dockerized
Mein komplettes Setup besteht aus dieser Datei: docker-compose.yml
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
services: shopware: image: dockware/shopware:6.7.15.1 container_name: shopware ports: - "80:80" - "443:443" - "2222:22" - "3306:3306" - "1025:1025" volumes: - db_volume:/var/lib/mysql # Fresh on every start, so stale mysqld socket lock files # can't block MySQL after an unclean shutdown tmpfs: - /var/run/mysqld:uid=101,gid=102,mode=0700 # Give MySQL time to shut down cleanly on `docker stop` # (default is 10s, then SIGKILL) stop_grace_period: 60s environment: - XDEBUG_ENABLED=0 volumes: db_volume: driver: local |
Ein paar Entscheidungen darin möchte ich kurz erklären.
Feste Shopware Version statt latest
Ich pinne das Image auf 6.7.15.1. So weiß ich jederzeit, gegen welche Shopware-Version ich teste, und ein docker compose pull bringt mir nicht unbemerkt eine neue Version ins Haus. Gerade wenn du gegen die Admin API entwickelst, ist das wichtig, denn Hauptversionen entfernen veraltete Felder und Routen.
Nur die Datenbank liegt im Docker Volume
Das benannte Volume db_volume sichert die MySQL-Daten. Produkte, Bestellungen und Einstellungen überleben damit einen Neustart des Containers.
Xdebug ist aus
Xdebug bremst PHP spürbar. Ich schalte es nur ein, wenn ich wirklich debuggen will, indem ich XDEBUG_ENABLED=1 setze und den Container neu starte.
SSH auf Port 2222
Auf dem Mac ist Port 22 bereits durch den eingebauten SSH-Dienst belegt. Deshalb mappe ich den SSH-Port des Containers auf 2222.
Die Shopware Ports im Überblick
| Host-Port | Container-Port | Dienst |
|---|---|---|
| 80 | 80 | Storefront und Admin (HTTP) |
| 443 | 443 | Storefront und Admin (HTTPS) |
| 2222 | 22 | SSH und SFTP |
| 3306 | 3306 | MySQL |
| 1025 | 1025 | Mailcatcher (SMTP) |
Den Shopware Docker-Container starten und stoppen
Gestartet wird der Shop mit:
|
1 |
docker compose up -d |
Beim ersten Start lädt Docker das Image herunter, das dauert je nach Leitung ein paar Minuten. Danach erreichst du die Storefront unter http://localhost und die Administration unter http://localhost/admin.
Zum Stoppen:
|
1 |
docker compose down |
Die Datenbank bleibt dabei im Volume erhalten. Willst du wirklich bei null anfangen, hängst du -v an. Dann wird auch das Volume gelöscht.
Die Shopware Zugangsdaten
dockware bringt feste Standardzugänge mit. Die sind öffentlich dokumentiert und nur für die lokale Entwicklung gedacht. Gib einen solchen Container deshalb niemals ins Internet frei.
| Dienst | Adresse | Benutzer | Passwort |
|---|---|---|---|
| Shopware Admin | http://localhost/admin | admin | shopware |
| MySQL | localhost:3306 | root | root |
| SSH und SFTP | localhost:2222 | dockware | dockware |
| Mailcatcher | http://localhost/mailcatcher | ohne Anmeldung | ohne Anmeldung |
Starte nach dem ersten Login im Backend den um Shopware startklar zu machen:

Mails abfangen mit Mailcatcher
Ein Detail, das ich sehr schätze: Shopware verschickt im Playground keine echten Mails. Bestellbestätigungen, Passwort-Mails und alles andere landen im Mailcatcher. Unter http://localhost/mailcatcher siehst du jede Mail, inklusive HTML-Ansicht. So kannst du Mail-Templates testen, ohne dass versehentlich ein echter Kunde etwas bekommt.

Den Quellcode lokal holen
Shopware liegt im Container unter /var/www/html. Um den Code in meiner IDE durchsuchen zu können, kopiere ich ihn heraus:
|
1 2 |
mkdir -p ./src docker cp shopware:/var/www/html/. ./src |
Hier liegt die erste Stolperfalle: Das ist eine Kopie, keine Verbindung. Änderungen in ./src landen nicht automatisch im Container. Für eigene Plugins hast du zwei Möglichkeiten:
- Du lässt deine IDE geänderte Dateien per SFTP über Port 2222 in den Container hochladen. PhpStorm kann das automatisch beim Speichern, VS Code mit einer SFTP-Erweiterung.
- Du bindest gezielt nur dein Plugin-Verzeichnis per Bind Mount ein, zum Beispiel
./src/custom/plugins/MeinPlugin:/var/www/html/custom/plugins/MeinPlugin.
Was du nicht tun solltest: einen leeren lokalen Ordner über das komplette /var/www/html mounten. Der Bind Mount verdeckt dann die vorinstallierte Shopware-Instanz, und der Shop ist leer.
Die Shopware-Konsole nutzen
Für alles, was über die Oberfläche hinausgeht, nutze ich bin/console direkt im Container:
|
1 2 3 4 |
docker exec -it shopware bin/console cache:clear docker exec -it shopware bin/console plugin:refresh docker exec -it shopware bin/console plugin:install --activate MeinPlugin docker exec -it shopware bin/console theme:compile |
Damit kannst du Plugins installieren, Caches leeren und Themes neu bauen, ohne dich erst per SSH anmelden zu müssen.
Die 2. Stolperfalle: Was wird eigentlich gespeichert?
Nur die Datenbank liegt in einem Volume. Alles andere lebt im Container selbst, also auch hochgeladene Produktbilder unter public/media und Plugins, die du per SFTP hineinkopiert hast.
Ein docker compose stop und start ist harmlos. Ein docker compose down entfernt dagegen den Container. Beim nächsten up entsteht ein frischer Container aus dem Image, die Datenbank aber bleibt alt. Danach verweist die Datenbank auf Bilder und Plugins, die es im Dateisystem nicht mehr gibt.
Für einen Playground ist das verkraftbar, du solltest es aber wissen. Ich nutze für Pausen deshalb stop und für einen echten Neuanfang down -v.
Auf eine neue Shopware-Version wechseln
Für ein Update ändere ich nur den Image-Tag in der docker-compose.yml. Die verfügbaren Versionen findest du auf Docker Hub unter dockware/shopware.
Weil das neue Image eine frisch installierte Shopware mitbringt, die alte Datenbank im Volume aber zur vorherigen Version gehört, setze ich bei einem Versionswechsel immer komplett neu auf:
|
1 2 |
docker compose down -v docker compose up -d |
Daten, die ich behalten will, exportiere ich vorher. Für einen Playground ist ein sauberer Neustart einfacher als jede Migration.
Mein Fazit
Mit knapp 20 Zeilen YAML habe ich einen vollständigen Shopware-Shop, den ich jederzeit starten, kaputt machen und zurücksetzen kann. Für API-Tests, Plugin-Entwicklung und zum Nachvollziehen von Kundenproblemen nutze ich ihn regelmäßig. Wenn du die beiden Stolperfallen kennst, also Kopie statt Verbindung beim Quellcode und nur die Datenbank im Volume, bekommst du damit in fünf Minuten eine sehr angenehme Spielwiese.
Häufige Fragen
Kann ich dockware auch produktiv einsetzen?
Nein. Die Images sind für Entwicklung und Tests gebaut, mit festen Standardpasswörtern und allen Diensten in einem Container. Für einen echten Shop brauchst du eine eigene, abgesicherte Installation.
Warum verwendest du nicht den Tag latest?
Weil ich reproduzierbar gegen eine bestimmte Shopware-Version testen will. Mit latest kann sich die Version bei jedem Pull ändern, ohne dass ich es merke.
Wie setze ich den Shop komplett zurück?
Mit docker compose down -v löschst du Container und Datenbank-Volume. Das nächste docker compose up -d startet mit einer frischen Installation.
Was mache ich, wenn Port 80 schon belegt ist?
Du kannst den Host-Port ändern, zum Beispiel auf "8080:80". Shopware erwartet aber die Domain, die im Verkaufskanal hinterlegt ist. Deshalb musst du in der Administration auch die Domain des Verkaufskanals auf http://localhost:8080 anpassen, sonst funktionieren Links und Weiterleitungen nicht.
Wie greife ich mit einem Datenbank-Tool auf die Daten zu?
Verbinde dich mit localhost, Port 3306, Benutzer root und Passwort root. Das funktioniert mit jedem MySQL-Client, zum Beispiel TablePlus, DBeaver oder der MySQL Workbench.
