Hey,
heute ein bisschen Code.
Man stelle sich vor, eine Datenbank läuft über docker-compose in einem Container:
db: image: mariadb volumes: - './data/mysql/data/:/var/lib/mysql' - './data/mysql/backups/:/opt/backups/'
Aufgabe: Sichere über einen Cronjob jede Datenbank in eine eigene .sql-Datei.
Das hat mich echt Nerven gekostet!
Über folgendes Snippet geht es aus dem Terminal heraus:
/usr/local/bin/docker-compose exec -db mysql -uroot -pMEINPASSWORT -N -e 'show databases' | tr "|+-" " " | grep -v -e '^[[:space:]]*$' | while read dbname; do dbnametrim=$(echo "$dbname" | tr -d '[:space:]'); if test ! -z "$dbnametrim"; then /usr/local/bin/docker-compose exec -d db mysqldump -uroot -pMEINPASSWORT --complete-insert "$dbnametrim" --result-file="/opt/backups/$dbnametrim.sql"; fi ; done
Was passiert hier? Getrennt nach Pipes die einzelnen Aufgaben der Befehle:

- alle Datenbanken auflisten
- Alle Pipes, Plusses und und Minusse entfernen, weil die DB-Namen in einer Tabellenstruktur ausgegeben werden
- Leere Zeilen entfernen
- Für jede Zeile: Führende und nachhängende Leerzeichen und Zeilenumbrüche entfernen und in Variable zwischenspeichern.
- Wenn ein DB-Name gesetzt ist, Export an den Container übergeben
Der innere compose-Befehl bekommt ein -d mit, damit er im Hintergrund ausgeführt wird und der Output nicht die while-Schleife durchbricht.
In einem Cronjob wird das aber nicht funktionieren. Dafür braucht der äußere compose-Befehl noch den -T Parameter, da wir im Cron kein interaktives Terminal haben.
Den Spaß noch in ein Bash-Script gewrappt und los:

#!/bin/bash rm ./data/mysql/backups/* /usr/local/bin/docker-compose exec -T db mysql -uroot -pMEINPASSWORT -N -e 'show databases' | tr "|+-" " " | grep -v -e '^[[:space:]]*$' | while read dbname; do dbnametrim=$(echo "$dbname" | tr -d '[:space:]'); if test ! -z "$dbnametrim"; then /usr/local/bin/docker-compose exec -d db mysqldump -uroot -pMEINPASSWORT --complete-insert "$dbnametrim" --result-file="/opt/backups/$dbnametrim.sql"; fi ; done
kill0rz