Lokale WordPress-Entwicklungsumgebung mit Docker Compose einrichten
WordPress lokal mit Docker Compose betreiben: offizielle Images für WordPress, MariaDB und WP-CLI, eigenes Theme per Bind-Mount, Kopie der Live-Datenbank mit wp search-replace und abgeschaltete Versanddienste.
WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Mehr dazu

Änderungen an Theme, Plugins oder PHP-Version direkt auf der Live-Website auszuprobieren, ist riskant: Ein Fehler ist sofort für Kunden sichtbar. Eine lokale Entwicklungsumgebung auf dem eigenen Rechner löst das. Mit Docker Compose starten Sie WordPress, MariaDB und WP-CLI mit einem Befehl, in genau den Versionen, die Sie festlegen, und werfen alles nach dem Test wieder weg. Diese Anleitung zeigt eine schlanke Compose-Datei mit den offiziellen Images, erklärt die Umgebungsvariablen, bindet Ihr eigenes Theme ein, holt eine Kopie der Live-Datenbank samt Adressumstellung und nennt die Stellen, an denen lokale Kopien typischerweise Ärger machen, etwa beim E-Mail-Versand.
Voraussetzungen
- Rechner: Windows, macOS oder Linux mit Docker Desktop bzw. Docker Engine und dem Compose-Plugin (Befehl
docker compose). 2 CPU-Kerne und 4 GB freier Arbeitsspeicher genügen; x86-64 oder ARM (Apple Silicon), die offiziellen Images gibt es für beide Architekturen. - Speicher: rund 2 GB für Images und Daten, zuzüglich der Größe Ihrer Uploads, falls Sie diese mitkopieren.
- Versionen: Diese Anleitung nutzt WordPress 7.1.2, PHP 8.4, WP-CLI 2.12.0 und MariaDB 11.8 LTS. Passen Sie die Image-Tags an die Versionen Ihrer Live-Website an; nur dann sagt ein lokaler Test etwas über die Produktion aus.
- Zugriff auf die Live-Website (nur für Schritt 5): Rolle Administrator sowie SSH mit WP-CLI oder ein Backup-Plugin, das einen Datenbank-Export liefert.
- Backup: Die lokale Umgebung verändert die Live-Website nicht. Bevor Sie dort einen Export ziehen, sollte trotzdem eine aktuelle Sicherung existieren.
Grundlagen zu Compose-Dateien, Volumes und Netzen erklärt die Anleitung Grundlagen zu Docker Compose und Stacks.
Schritt 1: Projektordner und .env anlegen
Jede Website bekommt einen eigenen Ordner. Darin liegen die Compose-Datei, die Zugangsdaten und später Ihr Theme-Code. So können Sie mehrere Projekte parallel betreiben, ohne dass sie sich stören.
mkdir -p ~/wp-lokal/firma && cd ~/wp-lokal/firma
mkdir -p themes
Legen Sie die Datei .env an. Compose liest sie automatisch und setzt die Werte in die compose.yaml ein. Die Passwörter sind nur lokal gültig, sollten aber trotzdem nicht aus Beispielen übernommen werden:
DB_NAME=wordpress
DB_USER=wordpress
DB_PASSWORD=lokal-geheim-1
DB_ROOT_PASSWORD=lokal-geheim-root-2
Nehmen Sie .env in .gitignore auf, falls der Ordner in einem Git-Repository liegt.
Verifizieren: ls -a zeigt .env und den Ordner themes.
Schritt 2: compose.yaml schreiben
Die Datei beschreibt drei Dienste. Die Tags sind festgeschrieben, damit ein späteres docker compose pull nicht unbemerkt eine andere Hauptversion lädt:
services:
db:
image: mariadb:11.8
restart: unless-stopped
environment:
MARIADB_DATABASE: ${DB_NAME}
MARIADB_USER: ${DB_USER}
MARIADB_PASSWORD: ${DB_PASSWORD}
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- dbdata:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
retries: 10
wordpress:
image: wordpress:7.1.2-php8.4-apache
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports:
- "127.0.0.1:8080:80"
environment: &wpenv
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: ${DB_NAME}
WORDPRESS_DB_USER: ${DB_USER}
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
WORDPRESS_DEBUG: 1
WORDPRESS_CONFIG_EXTRA: |
define( 'WP_ENVIRONMENT_TYPE', 'local' );
volumes:
- wpdata:/var/www/html
- ./themes/firma-child:/var/www/html/wp-content/themes/firma-child
- ./php.ini:/usr/local/etc/php/conf.d/lokal.ini:ro
wpcli:
image: wordpress:cli-2.12.0-php8.4
user: "33:33"
profiles: ["tools"]
depends_on:
- wordpress
environment:
<<: *wpenv
HOME: /tmp
volumes:
- wpdata:/var/www/html
- ./themes/firma-child:/var/www/html/wp-content/themes/firma-child
- ./import:/import
volumes:
dbdata:
wpdata:
Die wichtigsten Entscheidungen:
- Port an 127.0.0.1: Ohne diese Angabe ist die Testseite im ganzen Netzwerk erreichbar, etwa im Firmen-WLAN. Mit Debug-Modus und Kopie der Kundendaten ist das unnötig riskant.
- Healthcheck: Das MariaDB-Image enthält laut MariaDB-Dokumentation das Skript
healthcheck.sh. WordPress startet so erst, wenn die Datenbank Verbindungen annimmt; ohne diese Bedingung zeigt der erste Aufruf oft „Error establishing a database connection“. - Umgebungsvariablen: Das WordPress-Image schreibt die
WORDPRESS_DB_*-Werte nicht fest in diewp-config.php, sondern liest sie bei jedem Aufruf aus der Umgebung. Die Datenbank muss laut Image-Dokumentation bereits existieren; das übernimmtMARIADB_DATABASE. - WP-CLI als eigener Dienst: Die CLI-Images basieren laut Image-Dokumentation auf Alpine mit UID 82, das Apache-Image auf Debian mit UID 33. Ohne
user: "33:33"gehören Dateien, die WP-CLI anlegt, dem falschen Benutzer.HOME: /tmpvermeidet die Warnung „Failed to create directory '/.wp-cli/cache/': mkdir(): Permission denied.“, die wir im Test ohne diese Variable sahen. Überprofilesstartet der Dienst nur, wenn Sie ihn aufrufen.
Legen Sie zusätzlich eine kleine php.ini an. Das Image begrenzt Uploads im Test auf 2 MB (upload_max_filesize), was schon beim Hochladen eines Themes stört:
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
Verifizieren: docker compose config --quiet endet ohne Ausgabe. Eine Fehlermeldung weist auf einen Einrückungsfehler in der YAML-Datei hin.
Schritt 3: Starten und WordPress installieren
docker compose up -d
docker compose ps
docker compose run --rm wpcli wp core install \
--url=http://localhost:8080 --title="Firma lokal" \
--admin_user=admin --admin_password='lokal-admin-3' \
--admin_email=admin@example.test --skip-email
docker compose run --rm wpcli wp language core install de_DE --activate
Rufen Sie danach http://localhost:8080/wp-admin/ auf und melden Sie sich an. Prüfen Sie die Umgebung:
docker compose run --rm wpcli wp core version
docker compose run --rm wpcli wp eval 'echo wp_get_environment_type(), PHP_EOL;'
docker compose exec wordpress php -v
Im Test gab wp_get_environment_type() mit der Zeile aus WORDPRESS_CONFIG_EXTRA den Wert local aus, ohne sie production. Der Unterschied ist nicht nur kosmetisch: Plugins können darauf reagieren, und WordPress erlaubt Anwendungspasswörter bei local auch ohne HTTPS (Funktion wp_is_application_passwords_supported()). Die Werte aus php.ini griffen nach einem Neustart des Webservers; im Test meldete PHP danach 64M und 256M.
Verifizieren: docker compose ps zeigt db als „healthy“ und wordpress als „running“, das Dashboard ist auf Deutsch, und wp core version meldet 7.1.2.
Schritt 4: Eigenes Theme oder Plugin einbinden
Der Bind-Mount ./themes/firma-child macht den Ordner auf Ihrem Rechner im Container sichtbar. Sie bearbeiten die Dateien mit Ihrem gewohnten Editor, das Ergebnis sehen Sie nach dem Neuladen im Browser. Kopieren Sie Ihr Child-Theme dorthin oder legen Sie eines an, wie in Child-Theme anlegen beschrieben. Eigene Plugins binden Sie mit einer weiteren Zeile nach demselben Muster unter wp-content/plugins/ ein.
Binden Sie nur Ihren eigenen Code per Bind-Mount ein, nicht die komplette WordPress-Installation. Der WordPress-Kern und Fremd-Plugins bleiben im Volume wpdata. Das hält den Projektordner klein und vermeidet Rechteprobleme, die bei großen Bind-Mounts unter Windows und macOS häufig auftreten.
docker compose run --rm wpcli wp theme list
docker compose run --rm wpcli wp theme activate firma-child
Verifizieren: wp theme list zeigt firma-child als „active“, und eine Änderung an der style.css ist nach dem Neuladen sichtbar.
Schritt 5: Kopie der Live-Daten einspielen
Für realistische Tests brauchen Sie Inhalte und Einstellungen der echten Website. Exportieren Sie auf dem Live-Server die Datenbank und legen Sie die Datei in den Ordner import des Projekts:
# auf dem Live-Server
wp db export ~/live-export.sql
# lokal, nach dem Herunterladen nach ./import/
docker compose run --rm wpcli wp db import /import/live-export.sql
docker compose run --rm wpcli wp search-replace 'https://www.ihre-domain.de' 'http://localhost:8080' --dry-run
docker compose run --rm wpcli wp search-replace 'https://www.ihre-domain.de' 'http://localhost:8080'
Die Adressumstellung ist nötig, weil WordPress die Adresse der Website in der Datenbank speichert und sonst jede Anfrage auf die Live-Domain umleitet. Verwenden Sie dafür immer wp search-replace, nie ein SQL-REPLACE: Viele Optionen liegen als serialisierte PHP-Daten vor, in denen die Länge jeder Zeichenkette gespeichert ist. Im Test meldete der Probelauf vier Ersetzungen, zwei davon in wp_options mit dem Typ „PHP“, also in serialisierten Werten, die ein reines SQL-Replace beschädigt hätte. Der Probelauf mit --dry-run zeigt vorher, welche Tabellen betroffen sind.
Uploads kopieren Sie nur, wenn Sie sie brauchen, zum Beispiel per docker compose cp nach /var/www/html/wp-content/uploads. Die Kopie enthält personenbezogene Daten von Kunden, Bestellungen oder Formularen. Behandeln Sie den Rechner entsprechend, verschlüsseln Sie das Laufwerk und löschen Sie die Kopie nach dem Test.
Verifizieren: wp option get home gibt http://localhost:8080 aus, und ein Klick auf interne Links bleibt auf localhost.
Schritt 6: E-Mails und externe Dienste abschalten
Eine Kopie der Live-Website kann Kunden anschreiben: Bestellbestätigungen, Newsletter, Erinnerungen. Im Test schlug der Mailversand im Container fehl („sendmail: can't connect to remote host (127.0.0.1): Connection refused“), wp_mail() gab false zurück. Darauf sollten Sie sich nicht verlassen, denn ein importiertes SMTP-Plugin mit Live-Zugangsdaten versendet echte Mails. Deaktivieren Sie solche Plugins sofort nach dem Import oder leiten Sie den Versand auf einen Testserver um; die Anleitung Mailpit per Docker Compose einrichten zeigt, wie Sie einen solchen Dienst ergänzen.
docker compose run --rm wpcli wp plugin list --status=active
docker compose run --rm wpcli wp plugin deactivate wp-mail-smtp
Dasselbe gilt für Zahlungsanbieter im Live-Modus, Anbindungen an Warenwirtschaft oder CRM und Backup-Plugins, die in den externen Speicher der Live-Website schreiben würden.
Eine lokale Umgebung eignet sich gut, um Updates vorab zu testen. Die eigentliche Arbeit bleibt aber auf der Live-Website: Updates einspielen, Backups prüfen, Sicherheit im Blick behalten. Wer diese laufenden Aufgaben nicht selbst im Kalender halten möchte, kann sie abgeben: Die WordPress-Wartung von wordpressupdate.de übernimmt Updates von WordPress, Plugins und Themes mit Kompatibilitätsprüfung sowie wöchentliche Backups auf externen Speicher.
Verifizieren: Die Liste aktiver Plugins enthält keine Versand-, Zahlungs- oder Synchronisations-Plugins mit Live-Zugangsdaten.
Typische Fehler
| Beobachtung | Ursache | Lösung |
|---|---|---|
| „Error establishing a database connection“ | Datenbank noch nicht bereit oder Zugangsdaten falsch | Healthcheck mit service_healthy, Werte in .env prüfen |
| Weiterleitung auf die Live-Domain | Adressen nach dem Import nicht umgestellt | wp search-replace ausführen |
Failed to create directory '/.wp-cli/cache/' | WP-CLI ohne beschreibbares Home-Verzeichnis | HOME: /tmp im Dienst wpcli |
| Dateien gehören dem falschen Benutzer | CLI-Image mit UID 82 statt 33 | user: "33:33" |
| Upload bricht ab | upload_max_filesize 2 MB im Image | eigene php.ini einbinden, Container neu starten |
| Port bereits belegt | Anderes Projekt nutzt 8080 | Anderen Port wählen, --url und search-replace anpassen |
Häufige Fragen
Warum nicht einfach ein Tool wie Local oder XAMPP?
Das geht ebenfalls. Der Vorteil von Docker Compose: Die Versionen von PHP, Datenbank und WordPress stehen in einer Datei und lassen sich exakt an die Produktion anpassen, auch im Team. Der Nachteil ist die Einarbeitung in Docker.
Wie setze ich alles zurück?
docker compose down -v entfernt Container und die benannten Volumes samt Datenbank. Ihr Theme-Ordner bleibt erhalten, weil er auf Ihrem Rechner liegt.
Ersetzt das eine Staging-Umgebung?
Nicht vollständig. Lokal fehlen Webserver-Konfiguration, Caching und HTTPS des Hosters. Für Tests unter echten Bedingungen gibt es die Anleitung Staging-Umgebung für WordPress mit WP-CLI.
Kann ich eine andere PHP-Version testen?
Ja, über den Image-Tag, zum Beispiel ein anderes -phpX.Y-apache. Prüfen Sie im Docker Hub, welche Tags für Ihre WordPress-Version existieren, und passen Sie das CLI-Image an.
Testumfang
Die Bestandteile wurden in der Laborumgebung geprüft, die genau diese Images verwendet (wordpress:7.1.2-php8.4-apache, wordpress:cli-2.12.0-php8.4 mit --user 33:33, mariadb:11.8): Datenbankzugang über WORDPRESS_DB_*, WP_ENVIRONMENT_TYPE über WORDPRESS_CONFIG_EXTRA, PHP-Limits per eigener INI-Datei, wp search-replace mit Probelauf, Datenbank-Export, Verhalten von wp_mail() ohne Mailserver und die WP-CLI-Warnung ohne HOME. Die Compose-Datei als Ganzes und Docker Desktop unter Windows und macOS wurden nicht getestet.
Fazit
Mit einer Compose-Datei, festgeschriebenen Image-Tags und WP-CLI als eigenem Dienst entsteht in wenigen Minuten eine lokale WordPress-Umgebung, die der Produktion nahekommt und sich jederzeit zurücksetzen lässt. Achten Sie auf die Bindung an 127.0.0.1, die Adressumstellung mit wp search-replace und abgeschaltete Versanddienste. Die laufende Pflege der Live-Website übernimmt auf Wunsch die WordPress-Wartung von Marcel Schönfelder.


