WordPress im Docker Container mit Nginx Proxy

Ich habe bereits unzählige WordPress Installationen durchgeführt. Datenbank Benutzer erstellen, WordPress herunterladen und installieren. Heute habe ich aber eine neue Infrastruktur gebraucht. Ich wollte mehrere WordPress Instanzen im Rahmen verschiedener Test und Entwicklungstätigkeiten nutzen und auch anderen Bereitstellen. Ich habe dabei drei Anforderungen:

  1. Die Instanzen sind isoliert.
  2. Die Instanzen lassen sich automatisiert aufsetzen und löschen.
  3. Die Instanzen sind öffentlich über ein Nginx Proxy zugänglich. Sie haben ihre eigenen Subdomains. Das Ganze wird als virtual host (vhost) umgesetzt.
Aufbau der Infrastruktur

Docker bedient zusammen mit Docker-Compose ein Teil dieser Anforderungen. Damit kann man Instanzen automatisiert erzeugen und löschen. Das Ganze befindet sich in einer isolierten Umgebung. Nginx Proxys erzeugen ist auch gut machbar. Aber die Kombination aus einem Nginx Proxy im Host-System und Docker Container kann manchmal nicht auf Anhieb funktionieren. Ich möchte in diesem Beitrag kurz meine Lösung erläutern.

Docker-Compose

Ich nutze Docker-Compose für die Orchestrierung meiner kleinen Infrastruktur. Dafür habe ich die folgende docker-compose.yml in der offiziellen Docker Dokumentation gefunden und an meinen Anwendungsfall angepasst.

version: "3.3"
    
services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - wordpress_data:/var/www/html
    ports:
      - "127.0.0.1:9001:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress

volumes:
  db_data: {}
  wordpress_data: {}

Für jeden neuen vhost nutze ich einen anderen Port. Man muss den Port dementsprechend bei jedem vhost einmalig anpassen. Damit läuft auch bereits eine WordPress Instanz bestehend aus Apache und Php und zusätzlich einer eigene Mysql Instanz. Dadurch kann die Datenbank jedes einzelnen Docker-Containers problemlos gelöscht und neu aufgesetzt werden, ohne dass andere Anwendungen oder Instanzen betroffen sind.

Update: Durch das Ergänzen der localhost-IP an den freigegebenen Port lässt sich erreichen, dass der Port des Docker-Containers ausschließlich über den virtuellen Host erreichbar ist und nicht auch noch über die öffentliche IP Adresse mit Portangabe. Dies war vorher der Fall. Ich habe den localhost in die Konfiguration ergänzt:

    ports:
      - "127.0.0.1:9001:80"

Nginx Proxy

Mein Nginx vhost verbindet die Subdomain mit dem lokalen Dienst, der über den angegebenen Port zur Verfügung steht. Ich nutze ein SSL Zertifikat von „Let’s Encrypt“ und habe das im Vornherein beantragt. Die Konfiguration des vhosts sieht folgender maßen aus.

server {
	listen 80;
	listen [::]:80;

	server_name domain.example.com;

	listen 443 ssl;
	listen [::]:443 ssl;

	ssl_certificate /etc/letsencrypt/live/domain.example.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/domain.example.com/privkey.pem;

	if ($scheme = http) {
		return 301 https://$server_name$request_uri;
	}

	proxy_redirect off;
	location / {
		proxy_set_header        Host $host:$server_port;
		proxy_set_header        X-Real-IP $remote_addr;
		proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header        X-Forwarded-Proto $scheme;
		proxy_pass http://127.0.0.1:9001/;
	}
}

Dadurch lässt sich solch ein Nginx Proxy für WordPress umsetzen.

Ergebnis

Meine Instanz ist über die Subdomain erreichbar, lässt sich beliebig nutzen. Ich kann damit ein paar Anwendungsfälle für WordPress testen und evaluieren, bevor ich sie in meinen produktiven Umgebungen umsetze. Ich bin zufrieden mit diesem Aufbau. Die Infrastruktur ist vermutlich nicht perfekt, aber sie unterstützt mich dabei, meine Ideen umzusetzen. Es ist möglich, mit dieser Infrastruktur auch Instanzen für Demos anzulegen, die regelmäßig (z.B. über ein Cronjob) neu aufgesetzt werden.