345 lines
7.9 KiB
Markdown
345 lines
7.9 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
sudo -u www-data wp --path=/var/www/html db export /tmp/muckibackup.sql
|
|
```
|
|
|
|
### 1.3 wp-content sichern
|
|
|
|
```bash
|
|
tar czf /tmp/wp-content.tar.gz -C /var/www/html wp-content
|
|
```
|
|
|
|
### 1.4 Dateien auf den Docker-Host übertragen
|
|
|
|
```bash
|
|
scp user@prod-server:/tmp/muckibackup.sql ~/muckibackup/
|
|
scp user@prod-server:/tmp/wp-content.tar.gz ~/muckibackup/
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Verzeichnisstruktur anlegen
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
grep -m1 "CREATE TABLE" ~/muckibackup/muckibackup.sql
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Konfigurationsdateien erstellen
|
|
|
|
### 3.1 `.env`
|
|
|
|
```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`
|
|
|
|
```yaml
|
|
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`
|
|
|
|
```nginx
|
|
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
|
|
|
|
1. Portainer öffnen → **Stacks → Add Stack**
|
|
2. Name: `wordpress-test`
|
|
3. Build method: **Upload** → `docker-compose.yml` hochladen
|
|
4. Unter **Environment variables**: Inhalt der `.env` eintragen
|
|
5. **Deploy the stack**
|
|
|
|
Warten bis alle Container den Status **running** zeigen.
|
|
|
|
---
|
|
|
|
## 5. Datenbank importieren
|
|
|
|
### Option A: Via phpMyAdmin (empfohlen bis 512 MB)
|
|
|
|
1. Browser: `http://SERVERIP:8181`
|
|
2. Links: Datenbank **wordpress** anklicken
|
|
3. Reiter **Importieren** → Datei `muckibackup.sql` auswählen
|
|
4. **OK**
|
|
|
|
### Option B: Via CLI
|
|
|
|
```bash
|
|
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):
|
|
|
|
```sql
|
|
SELECT option_name, option_value
|
|
FROM wp_options
|
|
WHERE option_name IN ('siteurl', 'home');
|
|
```
|
|
|
|
URL ersetzen — im WordPress-Container (Portainer → wordpress-Container → Console):
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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-alpine` Image verwendet UID 82 für www-data. Bind-Mounts mit `sudo chown -R 82:82` setzen.
|
|
|
|
> **Nginx muss wp-content mounten:** Nginx benötigt denselben `wp-content` Bind-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-replace` wiederholt werden.
|
|
|
|
> **WP-CLI auf Produktion:** Immer als `sudo -u www-data wp --path=/var/www/html` ausführen, nicht als root — sonst wechseln Dateibesitzer auf root.
|