El problema#
Hace tiempo me pasó: un volumen Docker corrupto y sin backup limpio. Desde entonces, automatizo backups incrementales de mis volúmenes críticos. Te muestro cómo lo hago.
Requisitos#
- Servidor Docker en Linux (Debian/Ubuntu)
- Acceso SSH a almacenamiento remoto (NAS, VPS, etc.)
- rsync instalado
- Bot de Telegram configurado
- Permisos de sudo o acceso directo a volúmenes
Paso 1: Preparar el script de backup#
Creo /opt/docker-backup/backup.sh:
#!/bin/bash
BACKUP_SOURCE="/var/lib/docker/volumes"
BACKUP_DEST="user@remote-storage:/backups/docker-volumes"
LOG_FILE="/var/log/docker-backup.log"
CHECKSUM_FILE="/var/log/docker-backup.checksum"
TELEGRAM_TOKEN="YOUR_BOT_TOKEN"
TELEGRAM_CHAT="YOUR_CHAT_ID"
# Función para enviar alertas por Telegram
send_alert() {
local message=$1
local status=$2
if [ "$status" = "error" ]; then
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
-d chat_id="${TELEGRAM_CHAT}" \
-d text="❌ Docker Backup Error: ${message}"
else
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage" \
-d chat_id="${TELEGRAM_CHAT}" \
-d text="✅ Docker Backup: ${message}"
fi
}
# Crear directorio de log si no existe
mkdir -p $(dirname "$LOG_FILE")
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Iniciando backup incremental" >> "$LOG_FILE"
# Ejecutar rsync incremental
rsync -av --delete \
--backup-dir="/backups/docker-volumes/daily-$(date +%Y%m%d)" \
"$BACKUP_SOURCE/" "$BACKUP_DEST/" >> "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Backup completado exitosamente" >> "$LOG_FILE"
BACKUP_STATUS="exitoso"
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR en backup" >> "$LOG_FILE"
send_alert "Fallo en transferencia rsync" "error"
exit 1
fiPaso 2: Validación de integridad#
Agrego a backup.sh:
# Generar checksum local
find "$BACKUP_SOURCE" -type f -exec md5sum {} \; | sort > /tmp/local.checksum
# Verificar checksum remoto
ssh user@remote-storage "find /backups/docker-volumes -type f -exec md5sum {} \; | sort > /tmp/remote.checksum"
# Comparar
rsync --checksum "$BACKUP_SOURCE/" "$BACKUP_DEST/" --dry-run > /tmp/verify.log 2>&1
DIFF_COUNT=$(grep -c "would be transferred" /tmp/verify.log)
if [ "$DIFF_COUNT" -gt 0 ]; then
send_alert "Advertencia: ${DIFF_COUNT} archivos no sincronizados" "error"
else
send_alert "Integridad verificada: $(du -sh $BACKUP_SOURCE | cut -f1)" "ok"
fiPaso 3: Configurar cron#
Edito /etc/cron.d/docker-backup:
# Backup completo cada domingo a las 2 AM
0 2 * * 0 root /opt/docker-backup/backup.sh
# Backup incremental diario a las 3 AM
0 3 * * 1-6 root /opt/docker-backup/backup.sh
# Limpieza de backups antiguos (más de 30 días) cada viernes
0 4 * * 5 root find /backups/docker-volumes/daily-* -mtime +30 -deletePaso 4: Configurar Telegram#
Creo un bot en BotFather y obtengo el token. Luego:
# Probar conexión
curl -s -X POST "https://api.telegram.org/botTOKEN/sendMessage" \
-d chat_id="CHAT_ID" \
-d text="Test de conexión"Paso 5: Permisos y prueba#
chmod 750 /opt/docker-backup/backup.sh
chmod 640 /etc/cron.d/docker-backup
# Ejecutar manualmente para verificar
/opt/docker-backup/backup.shEn producción#
Reviso logs semanalmente:
tail -f /var/log/docker-backup.logHe detectado problemas temprano gracias a las alertas de Telegram. El script se ejecuta sin intervención manual y rsync solo transfiere lo que cambió. Con esto dormía más tranquilo.