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 lsEn 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/backupsPara 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
fiHago el script ejecutable:
chmod +x /usr/local/bin/docker-backup.sh3. 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=journalY /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.target4. Activar y verificar#
systemctl daemon-reload
systemctl enable docker-backup.timer
systemctl start docker-backup.timer
systemctl status docker-backup.timerVer logs:
journalctl -u docker-backup.service -f5. 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
fiLo 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é.