Betreibt man MySQL als Docker Container, hat man zwar alle Daten in einem persistenten Ordner, jedoch ist es keine gute Idee diese im laufenden Betrieb zu sichern. Ein Backup-Skript erledigt diesen Job zuverlässig.
Backup aller MySQL-Datenbanken von außerhalb des Docker Containers
Das folgende MySQL Backup-Skript läuft ausserhalb des Docker Containers und steuert die Datensicherung über Aufrufe der entsprechenden Befehle im Docker-Container. Alle Datenbanken werden einzeln komprimiert gesichert. Jede tägliche Sicherung hat einen eigenen Ordner. Nach 7 Tagen werden ältere Sicherungen automatisch gelöscht:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#!/bin/bash # # backup-mysql.sh 1.0.8 # # Dumps all databases to seperate files. # All files are created in a folder named by the current date. # Folders exceeding the defined hold time are purged automatically. # # (c)2015-2023 Harald Schneider # # Setup.start # HOLD_DAYS=7 TIMESTAMP=$(date +"%F") BACKUP_DIR="./backup" MYSQL_USR="root" MYSQL_PWD="YOUR_PASSWORD_HERE" CONTAINER=dstack-mysql MYSQL_CMD="docker exec $CONTAINER /opt/bitnami/mysql/bin/mysql" MYSQL_DMP="docker exec $CONTAINER /opt/bitnami/mysql/bin/mysqldump" MYSQL_CHECK="docker exec $CONTAINER /opt/bitnami/mysql/bin/mysqlcheck" # # Setup.end # Check and auto-repair all databases first # echo echo "Checking all databases - this can take a while ..." $MYSQL_CHECK -u $MYSQL_USR --password=$MYSQL_PWD --auto-repair --all-databases # Backup # echo echo "Starting backup ..." mkdir -p "$BACKUP_DIR/$TIMESTAMP" databases=`$MYSQL_CMD --user=$MYSQL_USR -p$MYSQL_PWD -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema)"` for db in $databases; do echo "Dumping $db ..." $MYSQL_DMP --force --routines --opt --user=$MYSQL_USR -p$MYSQL_PWD --databases "$db" | gzip > "$BACKUP_DIR/$TIMESTAMP/$db.gz" done echo echo "Cleaning up ..." find $BACKUP_DIR -maxdepth 1 -mindepth 1 -type d -mtime +$HOLD_DAYS -exec rm -rf {} \; echo "-- DONE!" |
Die Konfiguration wird über folgende Variablen gesteuert:
- HOLD_DAYS: Die Haltezeit der Datensicherung in Tagen
- BACKUP_DIR: Der Zielordner für alle Sicherungen
- MYSQL_USR, MYSQL_PWD: Der MySQL Root-User und dessen Passwort
- CONTAINER: Der Name des Docker Containers
- MYSQL_CMD, _DMP und _CHECK: Die Systembefehle zum Überprüfen und Sichern der Datenbanken
Nach Aufruf des Skripts befindet sich die aktuelle Datensicherung im Pfad ./backup.
MySQL-Backup direkt aus dem Docker-Container heraus
Betreibt man Docker unter Windows, lässt sich das Bash-Script leider nur umständlich über WSL oder andere Unix-Umgebungen aufrufen. Viel eleganter ist es, das MySQL Backup-Script in den Docker-Container zu packen und in dessen Linux-Umgebung zu integrieren. Das folgende Beispiel basiert auf dem Bitnami MySQL Image und Docker Compose.
Zuerst modifizieren wir das MySQL Backup-Skript, indem wir die Setup-Sequenz durch diesen Code austauschen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Setup.start # HOLD_DAYS=7 TIMESTAMP=$(date +"%F") BACKUP_DIR="/backup" MYSQL_USR="root" MYSQL_PWD=$MYSQL_ROOT_PASSWORD # Use this inside a Docker container # MYSQL_CMD=/opt/bitnami/mysql/bin/mysql MYSQL_DMP=/opt/bitnami/mysql/bin/mysqldump MYSQL_CHECK=/opt/bitnami/mysql/bin/mysqlcheck # # Setup.end |
Ausser HOLD_DAYS sollte keine der Variablen angepasst werden. BACKUP_DIR zeigt auf einen Ordner, der später auf einen persistenten Ordner ausserhalb des Containers gemapped wird. MYSQL_PWD holt sich das aktuelle Root-Passwort direkt aus den Umgebungsvariablen des Containers. Die zum Backup benötigten System-Kommandos sind auf die Pfade des Bitnami Docker Images angepasst.
Das Skript speichern wir im folgenden Pfad: ./resources/bin/backup-mysql.sh.
Das neue Image wird dann über das folgende Dockerfile zusammengebaut:
1 2 3 4 5 6 7 8 9 |
# Run with # docker-compose build FROM bitnami/mysql:5.7 USER 0 COPY resources/bin/* bin RUN mkdir /backup USER 1001 |
Danach starten wir den Build mit
1 |
docker-compose build |
Nun ergänzen wir unseren Eintrag in der Datei docker-compose.yml mit dem Pfad-Mapping auf /backup (letzte Zeile). Die Zeile mit “build:” verweist auf den Ordner mit unserem modifizierten Dockerfile.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# --- MySQL 5.7 # mysql: container_name: "dstack-mysql" image: bitnami/mysql:5.7 build: ./build/mysql environment: - MYSQL_ROOT_PASSWORD=YOUR_PASSWORD_HERE - MYSQL_USER=admin - MYSQL_PASSWORD=YOUR_PASSWORD_HERE ports: - '127.0.0.1:3306:3306' volumes: - ./docker/mysql/data:/bitnami/mysql/data - ./docker/mysql/backup:/backup |
./docker/mysql/backup ist hierbei unser lokaler Pfad, außerhalb des Docker-Containers und frei wählbar. In diesem Ordner werden dann alle Backups erzeugt.
Die Datensicherung der MySQL-Datenbanken wird dann von außerhalb des Docker Containers über den folgenden Befehl angestossen:
1 |
docker exec -it dstack-mysql /bin/backup-mysql.sh |
dstack-mysql ist der Name des Containers. Der Pfad zum Backup-Script darf hier nicht geändert werden, da er container-intern ist.
Nach Aufruf des Skripts befindet sich die aktuelle Datensicherung im Pfad ./docker/mysql/backup:/backup.