entwickler-gilde.de zieht um – Teil 1
Das erste Mal habe ich 2017 über unser bisheriges WordPress Setup gesprochen.
Seit damals hat sich das Setup konzeptionell nicht geändert.
Eine größere Veränderung war nur die Einführung von 3 redundanten OpenLDAP Servern um die Ausfallsicherheit zu verbessern (ggf. kommt dazu noch ein weiterer Blog Post).
Seit einiger Zeit, bin ich dabei die meisten Services auf ein Docker-Deployment umstellen. Eventuell letztendlich als Workload für einen größeren Kubernetes Cluster.
Hier soll nun als erster Schritt die Migration eines hosted WordPress (in einem LXC Container) zu einem Docker-Deployment beschrieben werden.
Schritt 1 – Snapshots
Als erster Schritt muss sowohl von der Datenbank, als auch vom WordPress Verzeichnis ein Schnappshot erstellt werden.
Die Datenbanken des MySQL Containers werden aktuell schon per cron-job täglich per mysqldump
in Snapshots abgespeichert. Es gilt also nun, diese Snapshots aus dem Container zu bekommen. Da ich für mein LXC Setup Proxmox vernwende, können wir in dem Container einen Mount-Point zum Host hinzufügen:
pct set 111 -mp0 /home/backup/111,mp=/home/backup
In dem LXC Container mit der ID 111 wird hier das Host Verzeichnis /home/backup/111
unter /home/backup
gemounted. D.h. nun können wir alle MySQL Dumps direkt in das Verzeichnis auf dem Host verschieben.
Just FYI: Das MySQL Script sieht in etwa so aus:
#!/bin/sh
PWD=`which pwd`
MYSQLDUMP=`which mysqldump`
MYSQL=`which mysql`
TAR=`which tar`
HOST=localhost
USER=root
PASS=XXXXXXXXX
ROOT=/home/backup
TARGET=${ROOT}/data/mysql
CMD_FILE="cmd.sql"
rm -R $TARGET/*
echo "SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('mysql','information_schema','performance_schema')" > ${ROOT}/$CMD_FILE
DBS=`$MYSQL --user=$USER --password=$PASS < ${ROOT}/$CMD_FILE`
DATE=`eval date +%Y-%m-%d`
echo "ROOT: ${ROOT}"
I=0
echo "saved $DATE"
for DB in $DBS; do
if [ ! $I = 0 ]; then
#echo "dumping $DB";
$MYSQLDUMP $DB --events --ignore-table=mysql.event --single-transaction --user=$USER --password=$PASS --add-locks --flush-logs > $TARGET/$DB.sql
echo "$DB saved"
cd $TARGET
$TAR cfj $DB.tar.bz2 $DB.sql
rm $DB.sql
cd $ROOT
echo ""
fi
I=$(( $I + 1 ))
done
echo "$I DBs saved"
echo "done"
rm $ROOT/$CMD_FILE
Als nächster Schritt wird ebenfalls das komplette WordPress Verzeichnis auf dem bisherigem NGINX Container gepackt. Und über einen entsprechenden Mount-Point auf den Host übertragen.
Wahlweise können die Archive nun bereits auf den Docker Host übertragen werden, auf dem dann demnächst das neue Deployment laufen soll.
Schritt 2 – Docker Host Setup
Der neue Docker Host verwenden als Front-End Proxy Traefik. Traefik wird hier sowohl das Certificate renewal, als auch ein Caching durchführen.
Der sehr große Vorteil von Traefik ist, dass man ohne einen Reload des Traefik Servers selbst, neue Deployments als neuen HTTP Service zur Verfügung stellen kann.
Traefik lässt sich hierbei so konfigurieren, dass es auf neue Docker Deployments reagiert und bei bestimmten Labels dann eine neue Service-Konfiguration aktiviert. Hierbei empfielt es sich ebenfalls, für Traefik ein separates Docker Network zu erstellen. Ich habe mich hier für den Namen traefik_default
entschieden.
Traefik selbst deploye ich, wie alle anderen Services auch, per docker-compose
file. Dies schaut wie folgt aus:
version: "3.3"
networks:
traefik_default:
external: true
services:
traefik:
image: "traefik:v2.10.7"
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
- "8082:8082"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "/docker/traefik/acme.json:/acme.json"
- "/docker/traefik/config:/etc/traefik"
- "/cache:/cache"
labels:
# Dashboard
- "traefik.http.routers.traefik.rule=Host(`traefik.adm.example.com`)"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.routers.traefik.tls.certresolver=leresolver"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.middlewares=auth_traefik"
- "traefik.http.middlewares.auth_traefik.basicauth.users=admin:$$apr1$$6…r$$.v…k/"
# global redirect to https
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=web"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
# middleware redirect
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
- "traefik.enable=true"
networks:
- traefik_default
Hinweise:
traefik.http.middlewares.auth_traefik.basicauth.users
sollte durch eigene, passende Werte gesetzt werden. Hier lässt sich konfigurieren, welche Benutzer per basic-auth auf das Traefik Dashboard Zugriff erhalten. Ggf. beschreibe ich in einem weiteren Blog Post noch, wie sich die User auch per LDAP verwalten lassen.traefik.adm.example.com
ist hier natürliche keine gültige Domain. Der Hostname sollte sich gegen die IP des Docker Hosts auflösen lassen. Z.B. durch einen Wildcard Record gegen*.adm.example.com
.acme.json
enthält die aktuelle Liste der per ACME erstellten TLS Zertifikate. Eventuell muss hier ein leeres JSON File{}
existieren, damit das Deployment funktioniert.- Entgegen vieler anderer Tutorials, wird hier Traefik nicht per CLI Parametern konfiguriert, sondern per separatem Config File
/docker/traefik/config
. Dies ist unter anderem notwendig geworden, weil durch die Nutzung von weiteren Plugins das Setup per CLI Parametern recht unübersichtlich hat werden lassen.
Die Datei /docker/traefik/config/traefik.yaml
sieht wie folgt aus:
################################################################
#
# Configuration sample for Traefik v2.
#
# For Traefik v1: https://github.com/traefik/traefik/blob/v1.7/traefik.sample.toml
#
################################################################
################################################################
# Global configuration
################################################################
global:
checkNewVersion: true
sendAnonymousUsage: true
################################################################
# EntryPoints configuration
################################################################
# EntryPoints definition
#
# Optional
#
entryPoints:
web:
address: :80
websecure:
address: :443
metrics:
address: :8082
################################################################
# Access logs configuration
################################################################
# Enable access logs
# By default it will write to stdout and produce logs in the textual
# Common Log Format (CLF), extended with additional fields.
#
# Optional
#
accessLog:
format: json
fields:
names:
StartUTC: drop
filters:
statuscodes: 200,300-302
retryattempts: true
minduration: 10ms
################################################################
# API and dashboard configuration
################################################################
# Enable API and dashboard
#
# Optional
#
api:
dashboard: true
pilot:
dashboard: true
################################################################
# Docker configuration backend
################################################################
providers:
# Enable Docker configuration backend
docker:
exposedByDefault: false
################################################################
# Certificate resolver configuration
################################################################
certificatesresolvers:
leresolver:
acme:
email: admin@consolving.de
storage: acme.json
tlschallenge: true
################################################################
# Metrics configuration
################################################################
metrics:
prometheus:
entryPoint: metrics
addrouterslabels: true
addServicesLabels: true
experimental:
plugins:
simplecache:
moduleName: "github.com/traefik/plugin-simplecache"
version: "v0.2.1"
Die Aktivierung des Metrics Endpoints ist hier optional und nur notwendig, falls ihr die Traefik Metriken via Prometheus abfragen wollt. Falls nicht, könnt ihr diese Zeilen einfach auskommentieren:
metrics:
address: :8082
Kleiner Pro-Tipp:
Je nach größe eurer WordPress-Installation empfiehlt es sich, noch einmal zu überprüfen, ob im Verzeichnis, wo die Docker Volumes liegen genug Platz vorhanden ist.
df -h /var/lib/docker/volumes/
Sollte dies nicht der Fall sein, besteht z.B. bei Cloud-Providern ein separates Volume zu mounten. Hierbei lässt sich dann gleich auch das komplette Docker Verzeichnis /var/lib/docker
auf ein externes Volume legen. Dies lässt sich durch ein paar einfache Schritte durchführen:
- Docker Service stoppen und disablen
- Docker Verzeichnix umbennen
mv /var/lib/docker /var/lib/docker2
- Docker Host runterfahren
- Externes Volume mounten unter
/var/lib/docker
- Docker Host starten
- Dateien von
/var/lib/docker2
nach/var/lib/docker
kopieren und access rights noch mal überprüfen. - Docker Service starten und enablen
/var/lib/docker2
löschen
Fazit
Hiermit ist das initiale Setup durchgeführt. Im nächsten Blog Post werden wir uns das Setup des Container Deployments ansehen.