Kostenvergleich Apps Preise Blog Termin buchen

Backup-Strategien für Docker-Infrastruktur: Der komplette Leitfaden

Backup-Strategien für Docker-Infrastruktur: Der komplette Leitfaden

Backups sind das Thema, vor dem sich alle drücken. Der Server läuft, die Anwendung funktioniert, die Benutzer sind zufrieden — warum Zeit investieren in etwas, das man hoffentlich nie braucht? Die Antwort kennt jeder, der schon einmal Daten verloren hat: Ein Backup, das man nicht hat, kann man nicht restoren.

Docker macht vieles einfacher — aber Backups nicht. Volumes, Datenbanken in Containern, verteilte Konfigurationen und die Frage, wie man einen konsistenten Snapshot erstellt, wenn 10 Container gleichzeitig laufen: Das erfordert eine durchdachte Strategie. In diesem Artikel zeigen wir, wie Sie Ihre Docker-Infrastruktur zuverlässig sichern.

Die 3-2-1-Regel: Grundlage jeder Backup-Strategie

Die 3-2-1-Regel ist seit Jahrzehnten der Goldstandard:

  • 3 Kopien Ihrer Daten (Original + 2 Backups)
  • 2 verschiedene Medien/Speicherorte (lokal + remote)
  • 1 Kopie offsite (physisch getrennt vom Server)

Angewandt auf Docker bedeutet das: Die Daten liegen im Docker-Volume (Original), werden lokal auf dem Server gesichert (Backup 1) und an einen externen Speicher übertragen (Backup 2, offsite). Wenn der Server abbrennt, die Festplatte stirbt oder ein Ransomware-Angriff alles verschlüsselt — das Offsite-Backup rettet Sie.

Was muss gesichert werden?

Ein Docker-Stack besteht aus mehreren Datenquellen, die alle gesichert werden müssen:

1. Datenbanken

MySQL/MariaDB, PostgreSQL, MongoDB — die Datenbank enthält den Kern Ihrer Anwendungsdaten. Ein Dateisystem-Snapshot der Datenbank-Dateien ist nicht ausreichend, weil die Daten im Speicher und auf der Festplatte inkonsistent sein können, wenn die Datenbank läuft.

Stattdessen: Logische Backups über die Datenbank-eigenen Tools:

# MySQL/MariaDB
docker compose exec -T database mysqldump -u root -p"$DB_ROOT_PW" --all-databases --single-transaction > backup.sql

# PostgreSQL
docker compose exec -T database pg_dump -U postgres --format=custom > backup.dump

# MongoDB
docker compose exec -T mongo mongodump --archive > backup.archive

Der Parameter --single-transaction bei MySQL ist entscheidend: Er erstellt einen konsistenten Snapshot ohne die Datenbank zu sperren — Ihre Anwendung läuft währenddessen normal weiter.

2. Docker Volumes

Volumes enthalten Anwendungsdaten, die nicht in der Datenbank liegen: hochgeladene Dateien, Medienbibliotheken, Konfigurationen, E-Mail-Speicher. Für die Sicherung gibt es mehrere Ansätze:

# Named Volumes sichern mit einem temporären Container
docker run --rm 
  -v myapp_data:/source:ro 
  -v $(pwd)/backups:/backup 
  alpine tar czf /backup/myapp-data-$(date +%Y%m%d).tar.gz -C /source .

# Oder direkt über den Host-Pfad (wenn bekannt)
tar czf backups/myapp-data.tar.gz -C /var/lib/docker/volumes/myapp_data/_data .

3. Docker Compose und Konfiguration

Ihre docker-compose.yml, Nginx-Konfigurationen, .env-Dateien und Custom-Configs. Diese liegen idealerweise in einem Git-Repository — das ist Ihr Konfigurationsbackup. Aber .env-Dateien mit Secrets werden nicht committet — diese müssen separat gesichert werden.

4. SSL-Zertifikate und Let’s Encrypt-Daten

Traefik speichert Zertifikate in acme.json. Verlieren Sie diese Datei, werden neue Zertifikate angefordert — das kann an Let’s Encrypts Rate Limits scheitern (maximal 5 Zertifikate pro Domain pro Woche).

Backup-Script: Ein praxistaugliches Beispiel

Ein komplettes Backup-Script für einen typischen Docker-Stack (Webanwendung + Datenbank + Volumes):

#!/bin/bash
set -euo pipefail

# Konfiguration
BACKUP_DIR="/opt/backups"
RETENTION_DAYS=30
DATE=$(date +%Y%m%d_%H%M%S)
COMPOSE_FILE="/opt/myapp/docker-compose.yml"

mkdir -p "$BACKUP_DIR/$DATE"

echo "==> Datenbank-Backup..."
docker compose -f "$COMPOSE_FILE" exec -T database 
  mysqldump -u root -p"$DB_ROOT_PW" 
  --all-databases --single-transaction 
  | gzip > "$BACKUP_DIR/$DATE/database.sql.gz"

echo "==> Volume-Backup..."
docker run --rm 
  -v myapp_uploads:/source:ro 
  -v "$BACKUP_DIR/$DATE":/backup 
  alpine tar czf /backup/uploads.tar.gz -C /source .

echo "==> Konfigurations-Backup..."
tar czf "$BACKUP_DIR/$DATE/config.tar.gz" 
  -C /opt/myapp 
  docker-compose.yml .env nginx/ config/

echo "==> Traefik-Zertifikate..."
cp /opt/traefik/acme.json "$BACKUP_DIR/$DATE/acme.json" 2>/dev/null || true

echo "==> Alte Backups aufräumen..."
find "$BACKUP_DIR" -maxdepth 1 -type d -mtime +$RETENTION_DAYS -exec rm -rf {} ;

echo "==> Backup-Größe: $(du -sh "$BACKUP_DIR/$DATE" | cut -f1)"
echo "Fertig: $BACKUP_DIR/$DATE"

Dieses Script per Cronjob täglich ausführen:

# /etc/cron.d/myapp-backup
0 3 * * * root /opt/myapp/backup.sh >> /var/log/myapp-backup.log 2>&1

Offsite-Backup: Daten vom Server wegbekommen

Ein lokales Backup schützt gegen versehentliches Löschen und Datenbankfehler. Gegen Hardware-Ausfall, Ransomware oder Rechenzentrum-Probleme hilft nur ein Offsite-Backup.

Restic: Das Schweizer Taschenmesser für Backups

Restic ist ein modernes Backup-Tool, das Deduplizierung, Verschlüsselung und inkrementelle Backups kombiniert. Es unterstützt zahlreiche Speicher-Backends:

# Repository initialisieren (einmalig)
restic -r s3:s3.eu-central-1.amazonaws.com/myapp-backups init

# Backup erstellen
restic -r s3:s3.eu-central-1.amazonaws.com/myapp-backups backup /opt/backups/latest/

# Alte Snapshots nach Retention-Policy bereinigen
restic -r s3:s3.eu-central-1.amazonaws.com/myapp-backups forget 
  --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

Restic verschlüsselt alle Daten client-seitig mit AES-256. Selbst wenn der Cloud-Speicher kompromittiert wird, sind Ihre Backups sicher. Deduplizierung sorgt dafür, dass nur geänderte Datenblöcke übertragen werden — das spart Bandbreite und Speicherplatz.

BorgBackup: Die Alternative

BorgBackup bietet ähnliche Features wie Restic — Deduplizierung, Verschlüsselung, Kompression — mit leicht höherer Kompressionsrate. Der Nachteil: BorgBackup unterstützt nativ nur SSH als Remote-Backend, keine S3-Speicher.

# Repository initialisieren
borg init --encryption=repokey ssh://backup-server/./myapp

# Backup erstellen
borg create ssh://backup-server/./myapp::backup-{now:%Y%m%d} /opt/backups/latest/

# Alte Backups bereinigen
borg prune ssh://backup-server/./myapp --keep-daily=7 --keep-weekly=4 --keep-monthly=6

Offsite-Speicher-Optionen

  • Hetzner Storage Box: Ab 3,81 Euro/Monat für 1 TB. Unterstützt SSH/SFTP, Samba, WebDAV. Rechenzentren in Deutschland. Ideal für BorgBackup.
  • Backblaze B2: 6 USD/TB/Monat. S3-kompatible API. Ideal für Restic. Erste 10 GB kostenlos.
  • AWS S3 (eu-central-1): Ab 0,023 USD/GB/Monat (Standard). Für größere Mengen S3 Glacier: 0,004 USD/GB/Monat. Bewährt, aber komplexere Preisstruktur.
  • Zweiter Server: Ein günstiger VPS (5 Euro/Monat) bei einem anderen Provider als reiner Backup-Empfänger. Maximale Unabhängigkeit.

Restore testen: Die vergessene Pflicht

Ein Backup, das nie getestet wurde, ist kein Backup — es ist eine Hoffnung.

Die häufigsten Gründe, warum Restores scheitern:

  • Backup ist korrupt: Der Dump-Prozess wurde unterbrochen, die Datei ist unvollständig.
  • Passwort/Schlüssel fehlt: Das verschlüsselte Restic-Repository kann ohne Passwort nicht geöffnet werden — und das Passwort lag nur auf dem Server, der gerade ausgefallen ist.
  • Inkompatible Version: Der MySQL-Dump wurde mit Version 8.0 erstellt, aber der neue Server läuft mit MariaDB 11. Subtile Unterschiede im SQL-Dialekt verhindern den Import.
  • Volumes fehlen: Die Datenbank wurde gesichert, aber die Upload-Dateien nicht. Die Anwendung zeigt überall Broken-Image-Icons.

Restore-Test-Prozedur

Führen Sie mindestens monatlich einen vollständigen Restore-Test durch:

# 1. Temporäre Umgebung hochfahren
docker compose -f docker-compose.yml -p restore-test up -d database

# 2. Datenbank-Restore
gunzip -c backup/database.sql.gz | 
  docker compose -f docker-compose.yml -p restore-test exec -T database 
  mysql -u root -p"$DB_ROOT_PW"

# 3. Volume-Restore
docker run --rm 
  -v restore-test_uploads:/target 
  -v $(pwd)/backup:/backup:ro 
  alpine tar xzf /backup/uploads.tar.gz -C /target

# 4. Anwendung starten und prüfen
docker compose -f docker-compose.yml -p restore-test up -d

# 5. Aufräumen
docker compose -f docker-compose.yml -p restore-test down -v

Dokumentieren Sie das Ergebnis jedes Restore-Tests. Wie lange hat der Restore gedauert? Gab es Fehler? Waren alle Daten vollständig?

Backup-Monitoring: Wissen, ob das Backup gelaufen ist

Ein Cronjob, der stillschweigend fehlschlägt, ist schlimmer als kein Backup — weil Sie glauben, gesichert zu sein. Backup-Monitoring ist unverzichtbar:

Push-basiertes Monitoring

Das Backup-Script meldet nach erfolgreichem Lauf an einen Monitor:

# Am Ende des Backup-Scripts:
curl -s "https://uptime-kuma.example.com/api/push/abc123?status=up&msg=OK&ping=$(du -sb $BACKUP_DIR/$DATE | cut -f1)"

In Uptime Kuma einen “Push”-Monitor einrichten, der alle 25 Stunden einen Push erwartet (bei täglichen Backups). Bleibt der Push aus, wird alarmiert.

Backup-Größe überwachen

Ein Backup, das plötzlich 0 Bytes oder 90 Prozent kleiner als üblich ist, deutet auf ein Problem hin. Loggen Sie die Backup-Größe und setzen Sie Schwellwerte:

# Backup-Größe prüfen
BACKUP_SIZE=$(du -sb "$BACKUP_DIR/$DATE" | cut -f1)
MIN_SIZE=10000000  # 10 MB Minimum

if [ "$BACKUP_SIZE" -lt "$MIN_SIZE" ]; then
  echo "WARNING: Backup nur $BACKUP_SIZE Bytes — erwartet mindestens $MIN_SIZE" >&2
  # Alert senden
  curl -s "https://ntfy.example.com/backups" -d "Backup zu klein: $BACKUP_SIZE Bytes"
  exit 1
fi

Spezialfälle: Datenbanken in Docker richtig sichern

MySQL/MariaDB: Konsistente Dumps

# Alle Datenbanken, transaktionskonsistent, komprimiert
docker compose exec -T database mysqldump 
  -u root -p"$DB_ROOT_PW" 
  --all-databases 
  --single-transaction 
  --routines 
  --triggers 
  --events 
  | gzip > database-$(date +%Y%m%d).sql.gz

--single-transaction startet eine Transaktion vor dem Dump — die Datenbank bleibt konsistent, ohne dass Tabellen gesperrt werden. --routines, --triggers und --events sichern auch Stored Procedures und Trigger.

PostgreSQL: Custom Format für flexiblen Restore

# Custom Format — ermöglicht selektiven Restore einzelner Tabellen
docker compose exec -T database pg_dump 
  -U postgres 
  --format=custom 
  --blobs 
  mydb > mydb-$(date +%Y%m%d).dump

# Alternativ: Plain SQL für einfacheres Lesen
docker compose exec -T database pg_dumpall 
  -U postgres 
  | gzip > all-databases-$(date +%Y%m%d).sql.gz

Redis: RDB-Snapshot

# Redis zum Snapshot zwingen und Datei kopieren
docker compose exec -T redis redis-cli BGSAVE
sleep 5
docker cp $(docker compose ps -q redis):/data/dump.rdb ./backup/redis-dump.rdb

Automatisierung mit docker-volume-backup

Für Teams, die nicht jedes Backup-Script selbst schreiben wollen, bietet docker-volume-backup eine fertige Lösung als Docker-Container:

services:
  backup:
    image: offen/docker-volume-backup:latest
    restart: unless-stopped
    environment:
      BACKUP_CRON_EXPRESSION: "0 3 * * *"
      BACKUP_FILENAME: "backup-%Y%m%dT%H%M%S.tar.gz"
      BACKUP_RETENTION_DAYS: "30"
      AWS_S3_BUCKET_NAME: "myapp-backups"
      AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}"
      AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}"
      # Datenbank vor dem Backup dumpen
      BACKUP_PRE_COMMAND: >
        docker exec $$(docker ps -qf name=database)
        mysqldump -u root -p"$DB_ROOT_PW" --all-databases --single-transaction
        > /tmp/pre-backup/database.sql
    volumes:
      - myapp_data:/backup/app-data:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro

Der Container erstellt automatisch tägliche Backups, rotiert alte Sicherungen und überträgt alles an S3-kompatiblen Speicher.

Disaster Recovery: Vom Backup zum laufenden System

Ein Backup ist nutzlos, wenn Sie im Notfall nicht wissen, wie Sie es einspielen. Dokumentieren Sie Ihren Restore-Prozess:

  1. Neuen Server aufsetzen: Docker und Docker Compose installieren.
  2. Repository klonen: git clone — Ihre docker-compose.yml und Konfiguration.
  3. .env-Datei wiederherstellen: Aus dem Backup oder Passwort-Manager.
  4. Datenbank-Restore: Container starten, Dump einspielen.
  5. Volume-Restore: Daten in die richtigen Volumes extrahieren.
  6. SSL-Zertifikate: acme.json wiederherstellen oder neue anfordern.
  7. DNS umstellen: Domain auf die neue Server-IP zeigen lassen.
  8. Verifizieren: Anwendung testen, Datenintegrität prüfen.

Dieses Runbook sollte so detailliert sein, dass jemand, der den Stack nicht kennt, den Restore durchführen kann. Testen Sie es — wenn möglich mit einer Person, die nicht am Aufbau beteiligt war.

Was kostet eine gute Backup-Strategie?

  • Offsite-Speicher: 4 bis 10 Euro/Monat für 100 GB bis 1 TB (Hetzner Storage Box oder Backblaze B2).
  • Tools: Restic und BorgBackup sind Open Source — kostenlos.
  • Arbeitszeit: Initiale Einrichtung: 2 bis 4 Stunden. Monatlicher Restore-Test: 1 Stunde. Laufende Wartung: minimal, wenn automatisiert.

Zum Vergleich: Die Kosten eines Datenverlusts — Geschäftsausfall, Wiederherstellungsversuche, verlorene Kundendaten, DSGVO-Meldepflichten — bewegen sich schnell im fünf- bis sechsstelligen Bereich. 15 Euro pro Monat für ein solides Backup-Setup ist die beste Investition, die Sie tätigen können.

Backups als Teil von Managed Hosting

Backup-Automatisierung, Offsite-Replikation und regelmäßige Restore-Tests sind integraler Bestandteil jedes professionellen Hosting-Angebots. Bei netzspitze.tech sind tägliche Backups mit 30 Tagen Retention, Offsite-Speicher und dokumentierten Restore-Prozeduren in jedem Paket enthalten.

In einem kostenlosen 15-Minuten-Call besprechen wir Ihre aktuelle Backup-Situation und wo die Lücken sind — bevor es ernst wird.

Bereit für eigene Infrastruktur?

15 Minuten Call – wir klären ob Self-Hosting für euch passt.

Termin buchen