Automatische Backups von PostgreSQL via Cronjob
Published: 2024-06-19 20:16:15

## Kontext
Um die Daten deiner Kunden zu sichern müssen diese Regelmäßig auf einem Server abgespeichert werden. Dieser muss unbeeinträchtigt sein, falls die Infrastruktur auf der deine Datenbank läuft kaputtgeht. Also am besten bei einem Anderen Provider, oder in einer anderen Gegend. Ich zeige dir hier wie du das über einen Cronjob einrichten kannst, der von deiner Datenbank im Docker-Container ein Backup erstellt.

## Befehl Testen
Dein Container braucht einen Namen, damit du in ihm einen Shell-Befehl auslösen kannst. In docker-compose.yml sieht das so aus:
```
  postgres:
    container_name: postgres
```

Jetzt kannst du mit `docker exec -it` In deinem Container einen Befehl auslösen. Probiere es mal aus:
```
docker exec -it mein_container_name pg_dumpall -U mein_datenbank_nutzer
```

Mit diesem Befehl sollte sich nun dein Bildschirm mit dem PostgreSQL dump füllen. Wie aber kannst du das ganze nun Speichern?
Durch Piping bringst du den Output vom pg_dumpall Befehl in eine Datei.
```
# mit gzip kannst du deine Datei komprimieren.
# mit $(date +%Y%m%d-%H%M%S) kriegt deine Datei einen einzigartigen Namen.
# mit dem \ Backslash kannst du deinen Befehl in mehrere Zeilen aufteilen
docker exec -it mein_container_name pg_dumpall -U mein_datenbank_nutzer \
| gzip -9c > db_backup_$(date +%Y%m%d-%H%M%S).sql.gz
```

Nun kannst du selbst dein Backup erstellen. Aber wie geht das ganze automatisch? Dazu kommen wir jetzt.


## Crontab bearbeiten
Regelmäßige Befehle werden auf deinem System in der Crontab eingestellt. Die crontab deines Nutzers kannst du mit `crontab -e` bearbeiten. 
Auf https://crontab.guru/ kannst du dir anschauen, was die Zeichen am Anfang deines cronjobs bedeuten. Wir können unser Backup zum Beispiel immer nachts um 03.22 Uhr ausführen:

```
22 3 * * * docker exec -it postgres pg_dumpall -U ruben | gzip -9c > /backup/location/db-$(date +%Y%m%d-%H%M%S).sql.gz
```

Um deine Crontab zu Testen aber am besten am Anfang jede Minute:
```
* * * * * /shell/befehl
```


`/backup/location/` ersetzt du durch einen vorübergehenden Speicherort auf deinem Server für die Backups. Z.B. home-Verzeichnis.

Jetzt musst du nur noch mit scp dein Backup zu einem anderen Server bringen. Das kannst du zum beispiel eine Stunde später tun...
```
22 4 * * * scp /backup/location/db-$(date +%Y%m%d)*.sql.gz mein_user@mein_server:/backup/location/
```

Und dein ursprüngliches Backup auf deinem Server Löschen damit dein Speicher nicht überfüllt wird...
```
22 5 * * * rm /backup/location/db-$(date +%Y%m%d)*.sql.gz
```

Das sind aber ganz schön viele cronjobs... Was wenn deine Datenbanksicherung länger dauert als eine Stunde? dann wird dein Backup nicht auf den Backupserver kopiert. D.h. es war quasi fehlerhaft.
Also das ganze lieber als bash-skript aufsetzen.
```
touch backup.sh
chmox +x backup.sh
vi backup.sh
```

So könnte dein backup.sh aussehen:
```
#!/bin/bash
DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_FILE=/home/user/db-$DATE.sql.gz
/usr/bin/docker exec -it postgres pg_dumpall -U ruben | gzip -9c > $BACKUP_FILE
echo "Backup $BACKUP_FILE erstellt" >> /home/user/backup.log
scp $BACKUP_FILE mein_user@mein_server:/backup/location/
rm $BACKUP_FILE
```

Und bei deiner Crontab fügst du es einfach so hinzu:
```
22 3 * * * /backup/script/location/backup.sh
```

Happy Coden!
Dein Ruben

[Mein Blog](rubenvoss.de)