WordPress Testumgebung mit Docker
Datum: 22. Juni 2026
Zielumgebung: Ubuntu Server, Docker, Portainer
Produktionssystem: WordPress 7.0, PHP 8.1, Apache, Ubuntu 22.04, MariaDB 10.6
Testsystem: Docker Compose, MariaDB 10.6, WordPress 7.0 FPM-Alpine, Nginx, phpMyAdmin, WP-CLI
1. Vorbereitung: Produktionssystem sichern
1.1 WP-CLI auf Produktionsserver installieren
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
wp --info
1.2 Datenbank exportieren
sudo -u www-data wp --path=/var/www/html db export /tmp/muckibackup.sql
1.3 wp-content sichern
tar czf /tmp/wp-content.tar.gz -C /var/www/html wp-content
1.4 Dateien auf den Docker-Host übertragen
scp user@prod-server:/tmp/muckibackup.sql ~/muckibackup/
scp user@prod-server:/tmp/wp-content.tar.gz ~/muckibackup/
2. Verzeichnisstruktur anlegen
mkdir -p ~/muckibackup/wp-content
cd ~/muckibackup
# wp-content entpacken
tar xzf wp-content.tar.gz -C ./wp-content --strip-components=1
# Berechtigungen setzen (UID 82 = www-data in Alpine)
sudo chown -R 82:82 ./wp-content
Tabellenprefix aus dem Dump prüfen:
grep -m1 "CREATE TABLE" ~/muckibackup/muckibackup.sql
3. Konfigurationsdateien erstellen
3.1 .env
MYSQL_ROOT_PASSWORD=sicheresRootPW
MYSQL_DATABASE=wordpress
MYSQL_USER=wp_user
MYSQL_PASSWORD=sicheresUserPW
WP_TABLE_PREFIX=wp_
WP_PORT=8088
PMA_PORT=8181
3.2 docker-compose.yml
services:
db:
image: mariadb:10.6
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- wp_db_data:/var/lib/mysql
networks:
- wp_internal
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
wordpress:
image: wordpress:7.0-php8.5-fpm-alpine
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: ${MYSQL_DATABASE}
WORDPRESS_DB_USER: ${MYSQL_USER}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
WORDPRESS_TABLE_PREFIX: ${WP_TABLE_PREFIX}
volumes:
- wp_core:/var/www/html
- /home/hans/muckibackup/wp-content:/var/www/html/wp-content
networks:
- wp_internal
nginx:
image: nginx:1.27-alpine
restart: unless-stopped
depends_on:
- wordpress
ports:
- "${WP_PORT}:80"
volumes:
- wp_core:/var/www/html:ro
- /home/hans/muckibackup/wp-content:/var/www/html/wp-content:ro
- /home/hans/muckibackup/nginx.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- wp_internal
phpmyadmin:
image: phpmyadmin:5.2-apache
restart: unless-stopped
depends_on:
- db
ports:
- "${PMA_PORT}:80"
environment:
PMA_HOST: db
PMA_USER: ${MYSQL_USER}
PMA_PASSWORD: ${MYSQL_PASSWORD}
UPLOAD_LIMIT: 512M
networks:
- wp_internal
wpcli:
image: wordpress:cli-php8.3
restart: "no"
depends_on:
db:
condition: service_healthy
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: ${MYSQL_DATABASE}
WORDPRESS_DB_USER: ${MYSQL_USER}
WORDPRESS_DB_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- wp_core:/var/www/html
- /home/hans/muckibackup/wp-content:/var/www/html/wp-content
networks:
- wp_internal
entrypoint: ["wp", "--allow-root"]
volumes:
wp_db_data:
driver: local
wp_core:
driver: local
networks:
wp_internal:
driver: bridge
3.3 nginx.conf
server {
listen 80;
root /var/www/html;
index index.php;
client_max_body_size 64M;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 300;
}
location ~ /\.ht {
deny all;
}
}
4. Stack in Portainer deployen
- Portainer öffnen → Stacks → Add Stack
- Name:
wordpress-test - Build method: Upload →
docker-compose.ymlhochladen - Unter Environment variables: Inhalt der
.enveintragen - Deploy the stack
Warten bis alle Container den Status running zeigen.
5. Datenbank importieren
Option A: Via phpMyAdmin (empfohlen bis 512 MB)
- Browser:
http://SERVERIP:8181 - Links: Datenbank wordpress anklicken
- Reiter Importieren → Datei
muckibackup.sqlauswählen - OK
Option B: Via CLI
docker exec -i wordpress-test_db_1 \
mysql -u wp_user -psicheresUserPW wordpress \
< ~/muckibackup/muckibackup.sql
6. Produktions-URL anpassen
Aktuelle URL aus der DB ermitteln (phpMyAdmin → wordpress → SQL-Reiter):
SELECT option_name, option_value
FROM wp_options
WHERE option_name IN ('siteurl', 'home');
URL ersetzen — im WordPress-Container (Portainer → wordpress-Container → Console):
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar search-replace \
'http://www.gh-muschitz.at' \
'http://SERVERIP:8088' \
--skip-columns=guid --allow-root --path=/var/www/html
7. Funktionstest
# HTTP-Status prüfen
curl -sI http://SERVERIP:8088 | head -3
# Uploads erreichbar?
curl -sI http://SERVERIP:8088/wp-content/uploads/2022/03/beispiel.jpg | head -3
# Logs beobachten
docker logs wordpress-test_wordpress_1 --tail=20
docker logs wordpress-test_nginx_1 --tail=20
- Testsystem:
http://SERVERIP:8088 - phpMyAdmin:
http://SERVERIP:8181
8. Theme-Dateien anpassen und deployen
8.1 Theme-Verzeichnis ermitteln
ssh user@prod-server "ls /var/www/html/wp-content/themes/"
8.2 Datei lokal bearbeiten
Theme-Dateien liegen im Testsystem unter:
/home/hans/muckibackup/wp-content/themes/THEME-NAME/
8.3 Geänderte Datei auf Produktion übertragen
# Backup der Originaldatei
ssh user@prod-server \
"cp /var/www/html/wp-content/themes/THEME-NAME/header.php \
/var/www/html/wp-content/themes/THEME-NAME/header.php.bak"
# Neue Datei übertragen
scp header.php user@prod-server:/var/www/html/wp-content/themes/THEME-NAME/header.php
# Berechtigungen prüfen
ssh user@prod-server \
"chown www-data:www-data /var/www/html/wp-content/themes/THEME-NAME/header.php"
8.4 Bilder/Assets auf Produktion übertragen
scp burgenlandlogo.png user@prod-server:/var/www/html/wp-content/uploads/2026/06/
ssh user@prod-server \
"chown www-data:www-data /var/www/html/wp-content/uploads/2026/06/burgenlandlogo.png"
9. Stack verwalten
# Stack stoppen
docker compose -f ~/muckibackup/docker-compose.yml down
# Stack neu starten
docker compose -f ~/muckibackup/docker-compose.yml up -d
# Alles löschen inkl. DB-Volumes (für Neustart von Null)
docker compose -f ~/muckibackup/docker-compose.yml down -v
Hinweise
Pi-hole Konflikt: Pi-hole belegt Port 80 auf allen Interfaces. Nginx immer auf einem anderen Port betreiben (z.B. 8088).
UID/GID: Das
fpm-alpineImage verwendet UID 82 für www-data. Bind-Mounts mitsudo chown -R 82:82setzen.
Nginx muss wp-content mounten: Nginx benötigt denselben
wp-contentBind-Mount wie WordPress — sonst werden statische Dateien (Bilder, CSS, JS) nicht gefunden und PHP gibt 404 zurück.
URL nach jedem DB-Import anpassen: Nach erneutem Import muss
search-replacewiederholt werden.
WP-CLI auf Produktion: Immer als
sudo -u www-data wp --path=/var/www/htmlausführen, nicht als root — sonst wechseln Dateibesitzer auf root.