Docker für PrestaShop: Entwicklungsumgebung einrichten
Docker für PrestaShop einrichten: Multi-Versions-Tests, Modul-Workflow, Datenbankverwaltung, Xdebug-Debugging und Produktionsüberlegungen.
Warum wir jeden PrestaShop-Shop auf Docker betreiben
Unsere gesamte Entwicklungs- und Staging-Infrastruktur bei mypresta.rocks läuft auf Docker, ein TrueNAS-Host, dedizierte Container wie ps176-dev, ps178-dev, ps8-dev und ps9-dev, ein gemeinsam genutztes ps-redis, ein Nginx Proxy Manager als vorgeschaltete Instanz. Jeden Fehler auf dieser Seite haben wir mindestens einmal selbst gemacht.
Das Problem: PS 1.7 verlangt PHP 7.1, PS 8.x verlangt 8.1, PS 9.x verlangt 8.3+. MySQL 5.7 gegenüber 8.0 ändert das Authentifizierungs-Plugin. Das nativ zu installieren ist der sichere Weg, einen Samstag mit Fehlersuche zu verbringen, statt Module zu schreiben. Jeder Container liefert exakt die Laufzeitumgebung mit, die sein PrestaShop erwartet.
- Tests über mehrere Versionen. PS 1.6, 1.7, 8.x und 9.x gleichzeitig. Ein Modul-Audit ist eine Sache von einem Nachmittag, nicht von einer Woche, in der LAMP-Stacks neu aufgebaut werden.
- Isolation. Jeder Shop hat sein eigenes PHP, MySQL und Dateisystem. Eine misslungene Installation kann nicht auf einen anderen übergreifen.
- Reproduzierbarkeit. Alles steckt in der
docker-compose.yml. Laptop, Staging, der Rechner eines Kollegen, dieselbe Einrichtung. - Einfaches Aufräumen.
docker compose down -vund alles ist weg.
Wir betreiben separate PrestaShop-Container von 1.6 bis 9.1 auf einer einzigen TrueNAS-Box. Die folgenden Muster sind das, was wir nach einem Jahrzehnt der Verfeinerung beibehalten haben.
Voraussetzungen
Docker installieren
Ubuntu/Debian: curl -fsSL https://get.docker.com | sh, anschließend sudo usermod -aG docker $USER. macOS: Docker Desktop: die Implementierung der Dateifreigabe in den Einstellungen auf VirtioFS umstellen. Windows: zuerst WSL2, dann Docker Desktop mit dem WSL2-Backend. Der Hyper-V-Modus ist langsamer; wir würden ihn meiden.
Die vier Konzepte, auf die es ankommt
- Image: schreibgeschützte Vorlage. Das offizielle ist
prestashop/prestashopauf Docker Hub. - Container: eine laufende Instanz. Mehrere aus einem Image, genau so funktionieren Einrichtungen mit mehreren Versionen.
- Volume: persistenter Speicher. Kein Volume, keine Daten nach dem Entfernen des Containers. Wir haben Testdaten verloren, weil wir das vergessen hatten.
- Netzwerk: virtuelles Netzwerk, damit Container sich gegenseitig erreichen können (PrestaShop ↔ MySQL).
Hardware
Rechnen Sie mit 1,5–2 GB RAM pro PrestaShop-Instanz. 16 GB sind auf einem Entwickler-Laptop für 2–3 Versionen angenehm. Unsere Entwicklungsmaschine hat 64 GB und NVMe, weil wir mehrere versionierte Container gleichzeitig betreiben. Mit drehenden Festplatten werden Sie Docker hassen, versuchen Sie es gar nicht erst.
Einrichtung mit zwei Containern
Legen Sie dies in eine docker-compose.yml:
version: '3.8'
services:
prestashop:
image: prestashop/prestashop:8.2
container_name: <your-shop>
ports:
- "8080:80"
environment:
- DB_SERVER=db
- DB_USER=prestashop
- DB_PASSWD=prestashop_password
- DB_NAME=prestashop
- PS_DOMAIN=localhost:8080
- PS_FOLDER_ADMIN=admin-dev
- PS_FOLDER_INSTALL=disabled
- ADMIN_MAIL=admin@yourshop.com
- ADMIN_PASSWD=admin_password_123
volumes:
- shop-data:/var/www/html
depends_on:
- db
db:
image: mysql:8.0
container_name: <your-shop>-db
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=prestashop
- MYSQL_USER=prestashop
- MYSQL_PASSWORD=prestashop_password
volumes:
- shop-db-data:/var/lib/mysql
volumes:
shop-data:
shop-db-data:
DB_SERVER muss exakt mit dem Dienstnamen (db) übereinstimmen, der mit Abstand häufigste Grund, warum ein frisches Compose-Setup scheitert. PS_FOLDER_INSTALL=disabled verhindert, dass der Installer bei jedem Neustart erneut läuft. docker compose up -d, dann mit docker compose logs -f prestashop beobachten; beim ersten Mal 1–2 Minuten einplanen.
Shop unter http://localhost:8080, Back Office unter http://localhost:8080/admin-dev.
Verwenden Sie für die Datenbank immer benannte Volumes. Ohne ein solches zerstört das Entfernen des Containers jedes Produkt, jede Bestellung und jeden Kunden. Wir haben einen halben Tag an Testdaten verloren, weil wir das bei einem „schnellen“ Wegwerf-Container vergessen hatten.
Tests über mehrere Versionen
Das ist der Fall, für den Docker gemacht wurde. Drei PrestaShop-Versionen nebeneinander, jede auf ihrem eigenen Port und ihrer eigenen Datenbank:
version: '3.8'
services:
ps176-dev:
image: prestashop/prestashop:1.7.6
container_name: ps176-dev
ports: ["8076:80"]
environment:
- DB_SERVER=<your-db-176>
- PS_DOMAIN=localhost:8076
# ... gleiches Muster wie oben
volumes:
- ps176-data:/var/www/html
networks: [ps-network]
<your-db-176>:
image: mysql:5.7
volumes: [your-db-176-data:/var/lib/mysql]
networks: [ps-network]
ps8-dev:
image: prestashop/prestashop:8.2
container_name: ps8-dev
ports: ["8082:80"]
environment:
- DB_SERVER=<your-db-8>
- PS_DOMAIN=localhost:8082
volumes:
- ps8-data:/var/www/html
networks: [ps-network]
<your-db-8>:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
volumes: [your-db-8-data:/var/lib/mysql]
networks: [ps-network]
ps9-dev:
image: prestashop/prestashop:9.0
container_name: ps9-dev
ports: ["8083:80"]
environment:
- DB_SERVER=<your-db-9>
- PS_DOMAIN=localhost:8083
volumes:
- ps9-data:/var/www/html
networks: [ps-network]
<your-db-9>:
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
volumes: [your-db-9-data:/var/lib/mysql]
networks: [ps-network]
networks:
ps-network:
driver: bridge
Wählen Sie ein Port-Schema. Unseres ist 8178 für PS 1.7.8, 8082 für 8.2, 8090 für 9.0. Jenseits von zehn Containern sind Portnummern nicht mehr einprägsam; ab da haben wir Nginx Proxy Manager davorgeschaltet und jedem Shop einen Hostnamen wie ps8-dev.mypresta.rocks gegeben. Tun Sie das am ersten Tag, wenn Sie über eine Handvoll hinausgehen.
Immer getrennte Datenbanken. Das Schema weicht zwischen den Hauptversionen voneinander ab; Migrationen würden sich gegenseitig beschädigen.
Warnung: docker network connect / disconnect auf einem laufenden Container schreibt die Port-Zuordnung neu. Wir haben zugesehen, wie es auf unserem NPM-Container stillschweigend Port 443 lahmgelegt und damit alle Seiten auf einen Schlag offline genommen hat. Definieren Sie das Netzwerk im Compose und erstellen Sie den Container neu, wenn Sie es ändern müssen.
Workflow für die Modulentwicklung
Binden Sie Ihr Modulverzeichnis per Bind-Mount ein. Jede Änderung ist sofort live. Der größte einzelne Vorteil, den Docker Ihnen für die Modularbeit verschafft:
volumes:
- ps8-data:/var/www/html
- /home/user/modules/my_module:/var/www/html/modules/my_module
Für Tests über mehrere Versionen binden Sie dasselbe Host-Verzeichnis in jeden Container ein. Eine Datei bearbeiten, drei Tabs aktualisieren. Wir binden jedes ~/modules/mpr* in alle Container ps178-dev, ps8-dev und ps9-dev ein, genau zu diesem Zweck.
Berechtigungen: die wiederkehrende Falle
Host-Dateien gehören Ihnen (UID 1000); Apache läuft als www-data (UID 33). PrestaShop versucht, in var/cache, img und modules zu schreiben, und bekommt eine Zugriffsverweigerung, deshalb scheitern Modul-Uploads bei frischen Setups.
# Interaktive MySQL-Sitzung
docker exec -it <your-shop>-db mysql -u root -p'root' prestashop
# Eine einzelne Abfrage ausführen
docker exec <your-shop>-db mysql -u root -p'root' -e "SELECT COUNT(*) FROM ps_product;" prestashop
Halten Sie ein fix-container-perms.sh bereit. Wir führen unseres häufiger aus, als uns lieb ist, besonders nachdem Module per rsync hineinkopiert wurden.
Cache
docker exec ps8-dev rm -rf /var/www/html/var/cache/*
Oder deaktivieren Sie den Template-Cache unter Erweiterte Parameter → Leistung während der aktiven Arbeit. Aktivieren Sie ihn wieder, bevor Sie die Arbeit als erledigt betrachten, cache-bezogene Fehler treten nur bei eingeschaltetem Cache zutage. Wenn die Produktion Redis verwendet, fügen Sie denselben Dienst lokal hinzu; Redis Dashboard & Key Manager ist nützlich, wenn Sie möchten, dass die PrestaShop-seitige Cache-Verdrahtung der Produktion entspricht, statt sie mit Filesystem-Cache vorzutäuschen.
Datenbankverwaltung
Halten Sie Testdatenbanken klein genug, um sie hin- und herzubewegen. Bevor Sie einen Live-Shop in Docker exportieren, bereinigen Sie veraltete Warenkörbe, Logs und temporäre Daten mit Database Cleanup oder einem gleichwertigen SQL-Bereinigungsdurchlauf, und ziehen Sie dann den Dump.
phpmyadmin:
image: phpmyadmin:latest
ports: ["9090:80"]
environment:
- PMA_HOSTS=<your-db-176>,<your-db-8>,<your-db-9>
- PMA_USER=root
- PMA_PASSWORD=root
networks: [ps-network]
phpMyAdmin
Der phpMyAdmin-Dienst oben verbindet sich mit jeder Datenbank im Netzwerk; die folgenden Befehle exportieren und importieren eine Datenbank:
# Export
docker exec <your-shop>-db mysqldump -u root -p'root' prestashop > backup.sql
# Import
docker exec -i <your-shop>-db mysql -u root -p'root' prestashop < backup.sql
Import und Export
mailpit:
image: axllent/mailpit
ports:
- "8025:8025" # Web-UI
- "1025:1025" # SMTP
networks: [ps-network]
Zwei Stolperfallen aus der Praxis: Bei komprimierten Dumps durch gunzip leiten, und beim Wiederherstellen über docker exec immer SET NAMES utf8mb4 an den Anfang setzen. Sonst landen UTF-8-Produktnamen doppelt kodiert, und die Behebung ist hässlicher als die Vorbeugung.
Persistent oder flüchtig
Persistent (benannte Volumes): alles, dessen Verlust Sie bedauern würden. Flüchtig: Installer-Tests. Wir halten einen flüchtigen PS-9.0-Container für die Frage „Installiert sich dieses Modul sauber auf einem leeren Shop?“ bereit, bei jedem Durchlauf frisch.
E-Mail-Tests mit Mailpit
Mailpit fängt ausgehende E-Mails ab, die über Mailpit gesendet werden, und zeigt sie mit der Dienstkonfiguration oben in einer Web-UI an. Das folgende Dockerfile ergänzt PrestaShop um Xdebug:
FROM prestashop/prestashop:8.2
RUN pecl install xdebug && docker-php-ext-enable xdebug
COPY xdebug.ini /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
Back Office → Erweiterte Parameter → E-Mail: SMTP mailpit, Port 1025, keine Verschlüsselung, keine Authentifizierung. Abgefangene Mails unter http://localhost:8025. Ein einziges gemeinsam genutztes Mailpit bedient jeden Entwicklungs-Shop in unserem Netzwerk.
Debugging mit Xdebug
Das offizielle Image bringt Xdebug nicht mit. Bauen Sie den Wrapper mit dem Dockerfile oben und konfigurieren Sie anschließend xdebug.ini und VS Code wie unten gezeigt:
[xdebug]
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.idekey=VSCODE
{
"version": "0.2.0",
"configurations": [{
"name": "Listen for Xdebug (Docker)",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html/modules/my_module": "${workspaceFolder}"
}
}]
}
Unter Linux existiert host.docker.internal standardmäßig nicht, fügen Sie extra_hosts: ["host.docker.internal:host-gateway"] hinzu. Wir haben dafür eine halbe Stunde verloren.
VS Code
Installieren Sie PHP Debug und fügen Sie die oben gezeigte JSON-Konfiguration in .vscode/launch.json ein. Die folgenden Befehle korrigieren die Container-Berechtigungen:
docker exec <your-shop> chown -R www-data:www-data /var/www/html/var
docker exec <your-shop> chown -R www-data:www-data /var/www/html/img
docker exec <your-shop> chown -R www-data:www-data /var/www/html/modules
pathMappings ist das, was den Breakpoint auslöst. Ohne es tut VS Code stillschweigend gar nichts.
PHPStorm
Einstellungen → PHP → Server: localhost + Container-Port, /var/www/html auf das Projekt abbilden. Xdebug-Port 9003 unter PHP → Debug, „Überwachung starten.“
Nützliche Befehle
| Aufgabe | Befehl |
|---|---|
| Alle Container starten | docker compose up -d |
| Alle Container stoppen | docker compose down |
| Stoppen und alle Daten löschen | docker compose down -v |
| Logs ansehen | docker compose logs -f |
| PS-Cache leeren | docker exec CONTAINER rm -rf /var/www/html/var/cache/* |
| MySQL-CLI | docker exec -it CONTAINER-db mysql -u root -p'PASS' prestashop |
| Datenbank exportieren | docker exec CONTAINER-db mysqldump -u root -p'PASS' prestashop > backup.sql |
| Datenbank importieren | docker exec -i CONTAINER-db mysql -u root -p'PASS' prestashop < backup.sql |
| Eine Shell im Container öffnen | docker exec -it CONTAINER bash |
| Ressourcenverbrauch prüfen | docker stats --no-stream |
| Nach Dockerfile-Änderungen neu bauen | docker compose up -d --build |
| PrestaShop-Konsole ausführen | docker exec CONTAINER php bin/console cache:clear --env=prod |
| Composer im Modul ausführen | docker exec -w /var/www/html/modules/my_module CONTAINER composer install |
Produktion: unsere ehrliche Meinung
Für die meisten Händler ist Docker ein Entwicklungswerkzeug. Die Produktion läuft in der Regel besser auf herkömmlichem Hosting, ein einzelner LAMP-Stack lässt sich leichter überwachen und übergeben, native Datei-I/O schlägt Docker-Volumes (PrestaShop lädt Tausende PHP-Dateien pro Anfrage), und die meisten PrestaShop-freundlichen Hoster geben Ihnen cPanel, nicht einen Docker-Daemon.
Docker macht sich in der Produktion bezahlt bei CI/CD, Kapazitätsspitzen bei Verkaufsaktionen, zehn oder mehr Shops oder Deployments ohne Ausfallzeit.
Compose vs. Kubernetes vs. Swarm. Compose bewältigt 20–30 Container auf einem einzigen Host, das, was wir betreiben, völlig ausreichend. Kubernetes bringt Auto-Scaling und Multi-Node-Orchestrierung mit, um den Preis eines echten Infrastruktur-Teams; bei PrestaShop haben wir bislang keinen Fall erlebt, in dem es die richtige Wahl war. Docker Swarm ist ein unbequemer Mittelweg, den wir auslassen würden. Die Community hat sich davon abgewandt. Und kompose (das Werkzeug zum „Umwandeln von Compose in k8s“) klingt großartig, bis Sie es ausprobieren und feststellen, dass die Ausgabe ebenso viel Handarbeit erfordert wie eine Neuerstellung von Grund auf.
Zwei Host-Einstellungen, die sich lohnen
live-restore: truein/etc/docker/daemon.json. Neustarts des Daemons töten laufende Container nicht mehr.- Benutzerdefinierter
data-rootauf einem schnellen SSD-Pool, nicht auf der Betriebssystem-Festplatte. Images und MySQL-Volumes wachsen; Systemfestplatten füllen sich unbemerkt.
Dinge, die schiefgehen
„Kann keine Verbindung zur Datenbank herstellen“
DB_SERVERstimmt nicht mit dem MySQL-Dienstnamen überein (identisch, Bindestriche inklusive).- MySQL hat den Start noch nicht abgeschlossen. Verwenden Sie einen Healthcheck und
depends_on: condition: service_healthy. - Container in unterschiedlichen Netzwerken: beide in eine benannte Bridge legen.
- MySQL 8.0 verwendet standardmäßig
caching_sha2_password; das mysqli von PrestaShop benötigtmysql_native_password. Fügen Siecommand: --default-authentication-plugin=mysql_native_passwordhinzu.
Langsame I/O unter macOS
Bind-Mounts unter macOS waren früher quälend langsam (10–30 s pro Seitenaufruf). Drei Lösungen: VirtioFS in den Einstellungen von Docker Desktop (der größte einzelne Gewinn), weniger einbinden (nur das Modulverzeichnis, der Rest auf einem benannten Volume), Mutagen (bidirektionale Dateisynchronisation, die die Mount-Schicht umgeht, Holzhammer, funktioniert).
SSL in der Entwicklung
Zahlungsmodule und Social Login verweigern reines HTTP. Nginx Proxy Manager beendet SSL für jeden Container, das, was wir nutzen, die sauberste Option. mkcert für lokal vertrauenswürdige Zertifikate. Traefik für automatische Erkennung und Bereitstellung.
MySQL frisst Ihren gesamten RAM
command: >
--innodb-buffer-pool-size=128M
--max-connections=50
Heben Sie bei Docker Desktop das Speicherlimit unter Einstellungen → Ressourcen auf mindestens 6 GB an, sobald Sie mehrere Container haben. Stoppen Sie die, die Sie nicht verwenden: docker stop ps178-dev.
Endlosschleifen bei der Neuinstallation
Wenn PrestaShop sich bei jedem Neustart neu installiert, wird entweder das Volume /var/www/html nicht persistiert oder PS_FOLDER_INSTALL=disabled wird nicht gelesen. Prüfen Sie, ob docker volume ls ein echtes (kein anonymes) Volume anzeigt.
Mixed Content nach einer Port-Änderung
docker exec <your-shop>-db mysql -u root -p'root' -e "
UPDATE ps_configuration SET value='localhost:8080'
WHERE name IN ('PS_SHOP_DOMAIN','PS_SHOP_DOMAIN_SSL');
UPDATE ps_shop_url SET domain='localhost:8080', domain_ssl='localhost:8080';
" prestashop
Eine Warnung: Führen Sie diese Abfrage niemals ohne Backup auf einem Live-Shop eines Kunden aus. Wir haben zugesehen, wie sie mitten am Nachmittag ein Produktions-Frontend lahmgelegt hat.
Weiterführende Lektüre
- Lokale PrestaShop-Entwicklung: XAMPP, WAMP, Docker & Linux einrichten: Docker im Vergleich zu den Alternativen
- Wichtige Tools für die PrestaShop-Entwicklung: was wir neben Docker im Einsatz behalten
- So erstellen Sie eine PrestaShop-Staging-Site: diese Muster bis ins Staging weitergeführt
- Leitfaden zur Fehlerbehebung: wenn der Container läuft, der Shop sich aber dennoch danebenbenimmt
- Performance-Optimierung und Performance Revolution: der nächste Halt nach „es funktioniert“
- PrestaShops offizielles Docker-Repository