Ir al contenido

Automatizar backups incrementales de volúmenes Docker con rsync y systemd timers

Rogelio Guerra Riverón
Autor
Rogelio Guerra Riverón
Construyendo mi propia infraestructura web desde cero. Aquí documento cada paso: servidores, redes, contenedores y lo que vaya surgiendo.

Automatizar backups incrementales de volúmenes Docker con rsync y systemd timers
#

Después de perder datos por un fallo de disco, decidí implementar un sistema robusto de backups para mis volúmenes Docker. La solución que uso hoy es simple, confiable y se ejecuta sin intervención manual.

El problema
#

Tener contenedores con datos persistentes sin respaldo es un riesgo que no me puedo permitir. Los backups deben ser:

  • Incrementales (no duplicar datos)
  • Automatizados (sin recordarlos)
  • Verificables (saber si son confiables)
  • Remotos (proteger contra fallos locales)

La solución: rsync + systemd timers
#

Uso rsync porque es eficiente con cambios incrementales y systemd timers porque no necesito cron ni servicios adicionales.

1. Preparar directorios y credenciales
#

Primero, identifico mis volúmenes Docker:

docker volume ls

En mi caso, los volúmenes están en /var/lib/docker/volumes/. Creo un directorio local de staging:

mkdir -p /mnt/backups/docker-volumes
chmod 700 /mnt/backups

Para el almacenamiento remoto, configuro SSH sin contraseña. Genero una clave dedicada:

ssh-keygen -t ed25519 -f /root/.ssh/backup_key -N "" -C "docker-backup"

La añado al servidor remoto en .ssh/authorized_keys del usuario de backup.

2. Script de backup con verificación
#

Creo /usr/local/bin/docker-backup.sh:

#!/bin/bash
set -e

BACKUP_DIR="/mnt/backups/docker-volumes"
REMOTE_USER="backup"
REMOTE_HOST="backup.example.com"
REMOTE_PATH="/backups/docker"
SSH_KEY="/root/.ssh/backup_key"
CHECKSUM_FILE="${BACKUP_DIR}/.checksums"

# Función para loguear
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a /var/log/docker-backup.log
}

log "Iniciando backup de volúmenes Docker"

# Copiar volúmenes locales
docker volume ls -q | while read volume; do
    SOURCE="/var/lib/docker/volumes/${volume}/_data"
    DEST="${BACKUP_DIR}/${volume}"
    
    if [ -d "$SOURCE" ]; then
        mkdir -p "$DEST"
        rsync -av --delete "$SOURCE/" "$DEST/" || log "Error en $volume"
    fi
done

log "Generando checksums"
find "$BACKUP_DIR" -type f -exec md5sum {} \; > "$CHECKSUM_FILE" 2>/dev/null || true

log "Sincronizando con servidor remoto"
rsync -avz \
    --delete \
    -e "ssh -i $SSH_KEY -o StrictHostKeyChecking=no" \
    "$BACKUP_DIR/" \
    "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/"

if [ $? -eq 0 ]; then
    log "Backup completado exitosamente"
    # Limpiar backups locales más antiguos de 7 días
    find "$BACKUP_DIR" -type f -mtime +7 -delete
else
    log "ERROR: Fallo en la sincronización remota"
    exit 1
fi

Hago el script ejecutable:

chmod +x /usr/local/bin/docker-backup.sh

3. Crear systemd service y timer
#

Creo /etc/systemd/system/docker-backup.service:

[Unit]
Description=Docker Volumes Backup Service
After=docker.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/docker-backup.sh
StandardOutput=journal
StandardError=journal

Y /etc/systemd/system/docker-backup.timer:

[Unit]
Description=Daily Docker Backup Timer
Requires=docker-backup.service

[Timer]
OnCalendar=daily
OnCalendar=*-*-* 02:00:00
Persistent=true

[Install]
WantedBy=timers.target

4. Activar y verificar
#

systemctl daemon-reload
systemctl enable docker-backup.timer
systemctl start docker-backup.timer
systemctl status docker-backup.timer

Ver logs:

journalctl -u docker-backup.service -f

5. Verificar integridad remota
#

En el servidor remoto, creo un script para validar:

#!/bin/bash
REMOTE_PATH="/backups/docker"
cd "$REMOTE_PATH"
md5sum -c .checksums > /tmp/backup-verify.log 2>&1
if [ $? -eq 0 ]; then
    echo "Backups íntegros" | mail -s "Backup OK" admin@example.com
else
    echo "ADVERTENCIA: Fallos en checksums" | mail -s "Backup FALLIDO" admin@example.com
fi

Lo ejecuto como cron diario.

Resultado
#

Llevo 6 meses con este sistema. Los backups se ejecutan automáticamente cada noche sin intervención. Los checksums me dan confianza en que los datos remoto están intactos. He recuperado volúmenes tres veces sin problemas.

Lo mejor: no he tenido que pensar en ello desde que lo configuré.