Dieser Blog-Eintrag beschreibt, wie man auf WordPress auf einem Docker-Host installieren und damit mehrere WordPress-Instanzen auf einem Host betreiben kann.
Ich betreibe die Docker-Container hinter einem Proxy-Server, der aber nicht als Container läuft. Der Proxy-Server leitet die HTTPS-Requests an die entsprechenden Docker-Container weiter.
Dieser Beitrag setzt ein vorinstalliertes Photon 3.0 inkl. Docker und Docker-Compose voraus. Siehe hier.
Die Docker-Container können über diverse Befehle gemanaged werden. Siehe dazu eine kleine Übersicht hier.
WordPress installieren
Wir installieren WordPress mit Hilfe von Docker Compose. Dazu erstellen wir ein template:
mkdir wordpress
cd wordpress
vi docker-compose.yml
Im yml-Script erstellen wir eine WordPress- inkl. DB-Instanz.
WordPress-Instanz
- Die WordPress-Instanz hat eine Abhängigkeit zur DB.
- Die WordPress-Files werden unter /var/www/html abgelegt
- der Host-Port 80 wird zur wordpress-Instanz port 80 weitergeleitet („80:80“)
- Die DB ist über Port 3306 anzusprechen (WORDPRESS_DB_HOST: db:3306)
- Der DB-User ist wordpress (WORDPRESS_DB_USER: wordpress)
- Das DB-Passowort ist zu setzen: WORDPRESS_DB_PASSWORD: <wordpress_db_password>
DB-Instanz
- Die DB-Files werden hier abgelegt: db_data:/var/lib/mysql
- Passort setzen: MYSQL_ROOT_PASSWORD: <mysql root password>
- Datenbank definieren: MYSQL_DATABASE: wordpress
- User definieren: MYSQL_USER <wordpress>
- DB-Passwort setzen: MYSQL_PASSWORD: (wordpress db password)
version: '3.3' services:
wordpress:
depends_on:
- db
image: wordpress:latest
volumes:
- wordpress_files:/var/www/html
ports:
- "8080:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: (wordpress_db_password)
db:
image: mysql:5.7
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: (mysql root password)
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: (wordpress db password)
volumes:
wordpress_files:
db_data:
Die letzten beiden Linien restellen lokale Verzeichnisse auf dem Photon-Host. Hier werden die WordPress- und SQL-Files abgespeichert. Diese Files überleben somit, wenn der container zerstört und neu generiert wird.
Die Volumes werden unter
cd /var/lib/docker/volumes
erstellt und bleiben bestehen. Dies solange bis die Volumes mittels
docker-compose down -v
zerstört werden.
WordPress Container starten
Nun kann der Container einfach gestartet werden. Dank Docker Compose braucht man nur noch einen Befehl. Docker Compose erkennt automatisch das YAML im aktuellen Verzeichnis, durchläuft die Konfiguration und startet die Container-Anwendung:
docker-compose up -d
Den Prozess kann man anzeigen lassen
docker ps
Nun ist über http://<ip>:8080 auf die WordPress-Instanz zugegriffen werden.
WordPress Container mit SSL erweitern
Das so bereitgestellte Container-Image bietet WordPress „out-of-the-Box“ über Port 80 an. Port 443 ist nicht aktiviert. Man geht dabei davon aus, dass die Verschlüsselung (https) eine zusätzliche, neue Funktion darstellt und damit über einen weiteren Container abzubilden ist. Dazu kann ein Proxy-Container aufgebaut werden, für den es auch bereits fertige Docker-Images gibt. Architektonisch mag das Sinn machen.
Ich möchte das aber nicht so umsetzen. Ich betreibe bereits einen Proxy-Server und dieser soll auch so weiter beibehalten werden. Ich verzichte also auf einen Proxy-Container und erweitere das WordPress-Image durch die SSL-Funktionalität. Damit das geht, muss ich das docker-compose.yml bzw. die WordPress-Container Beschreibung erweitern.
Als erstes erstelle ich ein zusätzliches File
vi wordpress/wp-init.sh
!/usr/bin/env bash
apt-get update
apt-get install -y --no-install-recommends ssl-cert
rm -r /var/lib/apt/lists/*
a2enmod ssl
a2dissite 000-default.conf
a2ensite apache2-vhosts.conf
docker-entrypoint.sh apache2-foreground
Dieses Bash-Script soll bei jedem Starten des Containers ausgeführt werden. Mittels diesem Script wird
– SSL nachinstalliert
– Die Default Konfig „000-default.conf“ auf dem Apachen entfernt und stattdessen
– eine neue Konfig „apache2-vhosts.conf“ installiert.
– Anschliessend wird der Apache neu gestartet.
Damit das Script funktioniert braucht es noch eine Apache-Config. Diese Config wird in den WordPress-Container gemappt und beim Container-Start aktiviert. Damit kann ich von ausserhalb des Containers, die Apache-Config manipulieren:
vi wordpress/apache2-vhosts.conf
NameVirtualHost *
<VirtualHost *:443>
ServerName domain.ch
DocumentRoot /var/www/html/
DirectoryIndex index.php
Options -Indexes
SSLEngine On
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
SSLCACertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
</VirtualHost>
Nun ist das das docker-compose.yml zu erweitern (siehe die markierten Erweiterungen):
version: '3.3'
services:
wordpress:
depends_on:
- db_node
image: wordpress:latest
volumes:
- wordpress_files:/var/www/html
- ./wp-init.sh:/usr/local/bin/apache2-custom.sh
- ./apache2-vhosts.conf:/etc/apache2/sites-available/apache2-vhosts.conf
ports:
- "8080:80"
- "8443:443"
restart: always
environment:
WORDPRESS_DB_HOST: db_node:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: (wordpress db password)
container_name: wordpress_web
command: "bash -c apache2-custom.sh"
db_node:
image: mysql:5.7
command: '--default-authentication-plugin=mysql_native_password'
volumes:
- db_data:/var/lib/mysql
ports:
- 6601:3306
restart: always
environment:
MYSQL_ROOT_PASSWORD: (wordpress root password)
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: (wordpress db password)
container_name: wordpress_db
volumes:
wordpress_files:
db_data:
Wie man sieht wird
– das wp-init.sh Skript in den Container gemappt
– Die Apache-Config apache2-vhosts.conf in den Container gemappt.
– Der Container um den Port 8443 erweitert, der Container-Intern auf 443 routet und
– Das Commando „bash -c apache2-custom.sh“ bei starten ausgeführt.
Damit startet der Container ab sofort mit aktiviertem SSL und der Apache-Container kann über das File apache2-vhosts.conf konfiguriert werden.
Reverse Proxy
Auf dem Reverse-Proxy wird nun einfach eine Reverse-Rule für den Container eingeführt. Der Reverse-Proxy leitet die HTTPS-Anfragen intern an den Container-Host mit Port 8443 weiter. Diese kann so aussehen:
<VirtualHost serverIp:80>
ServerAdmin info@domain.ch
ServerName www.domain.ch
ServerAlias domain.ch
RewriteEngine on
ReWriteCond %{SERVER_PORT} !^443$ RewriteRule ^/(.*) https://www.domain.ch/$1 [NC,R,L]
</VirtualHost>
<VirtualHost serverIp:443>
ServerAdmin info@domain.ch
ServerName www.domain.ch
#aktiviert SSL Unterstuetzung
SSLEngine On
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
SSLCertificateKeyFile /etc/letsencrypt/live/www.domain.ch/privkey.pem
SSLCertificateFile /etc/letsencrypt/live/www.domain.ch/cert.pem
SSLCertificateChainFile /etc/letsencrypt/live/www.domain.ch/chain.pem
# Regeln zum umleiten auf den internen Server
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / https://www.domain.ch:8443/
ProxyPassReverse / https://www.domain.ch:8443/
RequestHeader unset Accept-Encoding
ErrorLog /var/log/apache2/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
CustomLog /var/log/apache2/access.log combined
ServerSignature On
</VirtualHost>
SMTP auf WordPress-Container
Ich betreibe einen eigenen Mailserver. Ich stellte rasch fest, dass WordPress keine Mails über diesen Server versenden kann. Dies, weil das WordPress-Image einerseits grundsätzlich keinen SMTP-Agent mit dabei hat und andererseits mein Mailserver auch nicht aus dem Container heraus erreichbar war:
Um das Problem zu lösen habe ich mir einfach das Plugin „WP Mail SMTP“ installiert. Dieses erweitert WordPress um die Mailfunktion. Das Connectivity-Problem konnte ich mit einer einfach Erweiterung von /etc/hosts lösen:
192.168.xx.xx mx.domain.ch
Man beachte, dass ich die interne IP des Mailservers verwende.
Damit diese Erweiterung auch bei einem neuen Create des Containers übernommen wird, muss wordpress/wp-init.sh noch modifiziert werden:
#!/usr/bin/env bash
# modify /etc/hosts with mx.intelli.ch
cat >> /etc/hosts <<-EOF
/* mx.intelli.ch */
192.168.xx.xx mx.domain.ch
EOF
apt-get update
apt-get install -y --no-install-recommends ssl-cert # SSL
rm -r /var/lib/apt/lists/*
a2enmod ssl
a2dissite 000-default.conf
a2ensite apache2-vhosts.conf
# finally execute default command
docker-entrypoint.sh apache2-foreground
Links