Files
Docker-Compose-Backup-Script/backup.sh

231 lines
4.4 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
set -euo pipefail
############################
# Konfiguration
############################
SFTP_SERVER="sftp.domain.tld"
SFTP_PORT="22"
SFTP_USER="sftp-user"
SFTP_PASS="passw0rd"
REMOTE_DIR="/uploads"
EMAIL=""
############################
# Basis
############################
HOSTNAME=$(hostname)
DATE=$(date "+%Y-%m-%d_%H-%M")
BACKUP_DIR="/backups/docker"
LOG_DIR="/var/log/script-logs"
mkdir -p "$BACKUP_DIR" "$LOG_DIR"
PROJECT_NAME=""
ARCHIVE_FILE=""
LOG_FILE=""
############################
# Mail Funktion
############################
send_mail() {
STATUS="$1"
SUBJECT="[$HOSTNAME] Docker Backup $STATUS ($PROJECT_NAME)"
if command -v mail >/dev/null 2>&1; then
mail -s "$SUBJECT" "$EMAIL" -A "$LOG_FILE" <<EOF
Docker Backup Status: $STATUS
Host: $HOSTNAME
Projekt: $PROJECT_NAME
Datum: $DATE
Archiv: $ARCHIVE_FILE
Logfile im Anhang.
EOF
else
echo "Mail nicht installiert übersprungen."
fi
}
############################
# Fehlerbehandlung
############################
error_handler() {
echo "FEHLER aufgetreten!"
send_mail "FEHLER"
exit 1
}
trap error_handler ERR
############################
# Compose Projekte
############################
echo "Verfügbare Docker Compose Projekte:"
mapfile -t PROJECTS < <(
docker ps --format '{{.Label "com.docker.compose.project"}}' \
| sort -u \
| grep -v '^$'
)
if [[ ${#PROJECTS[@]} -eq 0 ]]; then
echo "Keine Compose-Projekte gefunden."
exit 1
fi
for i in "${!PROJECTS[@]}"; do
echo "[$((i+1))] ${PROJECTS[$i]}"
done
echo
read -p "Projekt auswählen (Nummer): " SELECTION
if ! [[ "$SELECTION" =~ ^[0-9]+$ ]] || (( SELECTION < 1 || SELECTION > ${#PROJECTS[@]} )); then
echo "Ungültige Auswahl."
exit 1
fi
PROJECT_NAME="${PROJECTS[$((SELECTION-1))]}"
LOG_FILE="$LOG_DIR/docker-backup-${PROJECT_NAME}.log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo
echo "===== Backup gestartet ====="
echo "Projekt : $PROJECT_NAME"
echo "Host : $HOSTNAME"
echo "Datum : $DATE"
echo
############################
# Container sammeln
############################
mapfile -t CONTAINERS < <(
docker ps \
--filter "label=com.docker.compose.project=$PROJECT_NAME" \
--format '{{.Names}}'
)
echo "Container im Stack:"
printf ' - %s\n' "${CONTAINERS[@]}"
echo
############################
# Mounts sammeln
############################
MOUNTS=()
for c in "${CONTAINERS[@]}"; do
mapfile -t PATHS < <(
docker inspect "$c" \
| jq -r '.[0].Mounts[] | select(.Type=="volume" or .Type=="bind") | .Source'
)
for p in "${PATHS[@]}"; do
[[ -d "$p" ]] && MOUNTS+=("$p")
done
done
mapfile -t MOUNTS < <(printf "%s\n" "${MOUNTS[@]}" | sort -u)
if [[ ${#MOUNTS[@]} -eq 0 ]]; then
echo "Keine gültigen Mounts gefunden."
exit 1
fi
############################
# Stack stoppen
############################
echo "Stoppe Stack..."
docker stop "${CONTAINERS[@]}" >/dev/null
sleep 3
############################
# Daten kopieren
############################
TMP_DIR="/tmp/docker-backup-$PROJECT_NAME"
rm -rf "$TMP_DIR"
mkdir -p "$TMP_DIR"
echo "Kopiere Daten..."
for mount in "${MOUNTS[@]}"; do
BASENAME=$(basename "$mount")
rsync -a "$mount/" "$TMP_DIR/$BASENAME/"
done
############################
# ZIP Archiv erstellen
############################
ARCHIVE_FILE="$BACKUP_DIR/${HOSTNAME}-${PROJECT_NAME}-${DATE}.zip"
echo "Erstelle ZIP Archiv..."
TOTAL_SIZE=$(du -sb "$TMP_DIR" | awk '{print $1}')
(
cd "$TMP_DIR"
zip -r -q - .
) | pv -s "$TOTAL_SIZE" > "$ARCHIVE_FILE"
echo "Archiv erstellt: $ARCHIVE_FILE"
############################
# Stack starten
############################
echo "Starte Stack..."
docker start "${CONTAINERS[@]}" >/dev/null
echo "Stack läuft wieder."
############################
# Optionaler Upload
############################
echo
read -p "Backup zum SFTP hochladen? (j/n): " DO_UPLOAD
if [[ "$DO_UPLOAD" == "j" ]]; then
if [[ -z "$SFTP_PASS" ]]; then
read -s -p "SFTP Passwort eingeben: " SFTP_PASS
echo
fi
echo "Starte Upload..."
sshpass -p "$SFTP_PASS" \
scp -P "$SFTP_PORT" "$ARCHIVE_FILE" \
"$SFTP_USER@$SFTP_SERVER:$REMOTE_DIR/"
echo "Upload abgeschlossen."
fi
############################
# Cleanup
############################
rm -rf "$TMP_DIR"
echo "Backup erfolgreich abgeschlossen."
send_mail "ERFOLGREICH"
echo "===== Fertig ====="
exit 0