./data war ein Bind-Mount relativ zum Git-Checkout - bei Dokploy wird das Repo pro Deploy frisch geklont, ein per CLI angelegter Nutzer war nach einem reinen Routing-Redeploy spurlos verschwunden. Betraf nicht nur Nutzer, sondern denselben Api:DataPath für Ereignis-Log/Snapshots/ Anhänge - also jeden Server-Datenbestand bei jedem Redeploy. - docker-compose.yml: Named Volume "api-data" statt Bind-Mount, lebt unabhängig vom Checkout im Docker-Daemon. - backup.sh: auf volume-basiertes Backup umgeschrieben (Alpine- Hilfscontainer statt direktem Host-Pfad). - docker/README.md, TODO.md 10.2.4: Vorfall dokumentiert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
41 lines
1.8 KiB
Bash
Executable File
41 lines
1.8 KiB
Bash
Executable File
#!/bin/sh
|
|
# Sichert das Docker-Volume "api-data" (Ereignis-Logs, Snapshots, Anhänge, Nutzer) als
|
|
# komprimiertes Tar-Archiv. Läuft über einen kurzlebigen Alpine-Container mit Zugriff auf das
|
|
# Volume - kein direkter Host-Pfad, seit das Volume kein Bind-Mount mehr ist (siehe
|
|
# docker-compose.yml: Dokploy-Redeploys klonen das Repo neu, ein Bind-Mount relativ zum
|
|
# Checkout würde dabei geleert, siehe TODO.md 10.2.4).
|
|
#
|
|
# Der volle Docker-Volume-Name ist "<compose-projektname>_api-data" - bei einem lokalen
|
|
# "cd docker && docker compose up" ist das "docker_api-data" (Default unten), bei Dokploy der
|
|
# App-Slug, z.B. "lehrerapp-syncserver-xyz_api-data". Im Zweifel prüfen mit:
|
|
# docker volume ls | grep api-data
|
|
# und den echten Namen per LEHRERAPP_DATA_VOLUME übergeben:
|
|
# LEHRERAPP_DATA_VOLUME=lehrerapp-syncserver-xyz_api-data /pfad/zu/docker/backup.sh
|
|
#
|
|
# Aufruf z.B. per Cron:
|
|
# 0 3 * * * LEHRERAPP_DATA_VOLUME=... /pfad/zu/docker/backup.sh >> /pfad/zu/docker/backup.log 2>&1
|
|
set -eu
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
BACKUP_DIR="$SCRIPT_DIR/backups"
|
|
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
|
|
KEEP_DAYS=30
|
|
VOLUME_NAME="${LEHRERAPP_DATA_VOLUME:-docker_api-data}"
|
|
|
|
if ! docker volume inspect "$VOLUME_NAME" >/dev/null 2>&1; then
|
|
echo "Docker-Volume '$VOLUME_NAME' nicht gefunden (docker volume ls | grep api-data) - nichts zu sichern." >&2
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "$BACKUP_DIR"
|
|
docker run --rm \
|
|
-v "$VOLUME_NAME":/data:ro \
|
|
-v "$BACKUP_DIR":/backup \
|
|
alpine:3 \
|
|
tar -czf "/backup/lehrerapp-data-$TIMESTAMP.tar.gz" -C /data .
|
|
|
|
# Alte Backups jenseits von KEEP_DAYS aufräumen, damit das Verzeichnis nicht unbegrenzt wächst.
|
|
find "$BACKUP_DIR" -name 'lehrerapp-data-*.tar.gz' -mtime "+$KEEP_DAYS" -delete
|
|
|
|
echo "Backup erstellt: $BACKUP_DIR/lehrerapp-data-$TIMESTAMP.tar.gz"
|