Ich mache das so, dass ich vor dem Aufruf von docker-entrypoint.sh ein Script in den Hintergrund schicke, dass wartet, bis MariaDB hochgefahren ist und das Script sich verbinden kann. Anschließend prüft es anhand der eingestellten Parameter eine SFTP-Adresse, ob dort ein Backup in Form eines Dumps liegt. Wenn dort ein Backup liegt, wird es gezogen und der Dump eingespielt. Anschließend läuft per Cron im Container noch regelmässig ein Dump, der die Dump-Datei an gleiche SFTP-Adresse ablegt.
Sieht dann so aus:
Das von aussen via docker-compose mitgegebene ENV-File(relevanter Ausschnitt):
Code:
MYSQL_ROOT_PASSWORD=geheim
MYSQL_ALLOWED_IPS=192.168.1.10 192.168.240.0/24 4.1.123.7
MYSQL_SFTP_BACKUP_SERVER_NAME=mein.sftp.server.domain.tld
MYSQL_SFTP_BACKUP_SERVER_PORT=22
MYSQL_SFTP_BACKUP_SERVER_USER=backupuser
SSH_PRIVATE_KEY=-----BEGIN RSA PRIVATE KEY-----\niyHTir....P/7j0yOgsQnoL\n-----END RSA PRIVATE KEY-----
app_start Mein Docker-Entrypoint
Code:
#!/bin/sh
if [ -f /ENV ] ; then
. /ENV
export MYSQL_ROOT_PASSWORD
/usr/local/bin/setup_ssh_key
/usr/local/bin/setup_iptables
{
/usr/local/bin/mysql_init
/usr/sbin/cron
} >/tmp/mysql_init.log 2>&1 &
fi
# Den ursprünglichen docker-entrypoint aufrufen
/usr/local/bin/docker-entrypoint.sh mysqld
# falls etwas schiefläuft, noch ein sleep, das man den laufenden Container nochmal untersuchen kann
echo
echo sleeping
echo
sleep 3600
mysql_init Die Datenbankinitialisierung
Code:
#!/bin/bash
[ -f /ENV ] && . /ENV
echo -e "[mysql]\nuser=root\npassword=$MYSQL_ROOT_PASSWORD\n\n" >/root/.my.cnf
echo -e "[mysqldump]\nuser=root\npassword=$MYSQL_ROOT_PASSWORD\n" >>/root/.my.cnf
# warten bis mariadb mit den übergebenen Zugangsdaten erreichbar ist
/usr/local/bin/wait_for_mysql
# Dump ggf. holen und einspielen
/usr/local/bin/mysql_restore
# Nutzer und Datenbanken, die noch nicht existieren anlegen
/usr/local/bin/initialize-databases
/usr/bin/mysql -e 'flush privileges;'
Grundsätzlich möchte ich später mit Images arbeiten, die in einer Registry abgelegt sind. Da muss ich das noch verbessern, dass die ENV Datei aus den Umgebungsvariablen erzeugt wird und nicht per Dockerfile kopiert wird, denn das geht ja später nicht mehr, wenn nur noch das Image verwendet werden kann. Der Hintergrund ist, das man ein generisches Image ohne Konfigurationsdaten hat, bei dem die Werte beim Starten mitgegeben werden. Also entweder per Umgebungsvariablen(docker), in einer ENV-Datei(docker-compose) oder per Config-Map(kubernetes).
Auch da im Hintergrund noch einen cron laufen zu lassen ist wohl nicht ganz so sauber.
Ich hatte auch schon mal eine Variante mit einem extra Dump-Container. Da ich aber für den Dump-Container ein etwas anderes Setup hatte(Schlankes Alpine Linux Image statt dem offiziellen Mariadb-Image mit Ubuntu), hat das Probleme verursacht, dass mysqldump nicht exakt mit der Version von mariadb zusammengepasst hat(Es gibt da eine Inkompatibilität mit mariadb/mysqldump bei 10.3/10.4 ab der man ein älteres mysqldump nicht mehr verwenden kann.). Um solchen Inkompatibilitäten aus dem Weg zu gehen, habe ich dann beschlossen, den Dump innerhalb des DB-Containers auszuführen.
Dass man iptables verwenden kann, braucht es die docker-Option: --cap-add=NET_ADMIN, der dem Docker-Container auf dem Host-System(!) die Rechte zur Netzwerkverwaltung(Siehe man 7 capabilties).
Lesezeichen