Hace unos meses un cliente perdió la base de datos de su tienda online porque su proveedor de hosting sufrió un fallo de disco. Tenía backups, sí, pero de máquinas virtuales completas. Restaurar una VM de 80 GB para recuperar una base de datos de 2 GB le costó horas de downtime y ventas perdidas. Si usas Docker, este escenario es evitable con una estrategia de backup pensada para contenedores.
Por qué los backups tradicionales no sirven para Docker
Los contenedores Docker cambian las reglas del juego respecto a los servidores tradicionales. Entender estas tres diferencias es clave para diseñar un backup efectivo:
- Los contenedores son efímeros. Un contenedor puede destruirse y recrearse en segundos. Hacer backup del sistema de ficheros del contenedor no tiene sentido porque la aplicación se reconstruye desde la imagen Docker.
- Los datos importantes están en volúmenes y bind mounts. Las bases de datos, los archivos subidos por usuarios y la configuración persistente viven fuera del contenedor, en volúmenes de Docker o carpetas montadas del host.
- Las imágenes se reconstruyen, los datos no. Tu
Dockerfiley el código fuente están en Git. Puedes reconstruir la imagen en cualquier momento. Pero los datos de tus usuarios, si los pierdes, no hay Dockerfile que los recupere.
Por eso, en Docker no se hace backup de contenedores: se hace backup de volúmenes y de configuración (ficheros docker-compose.yml, variables de entorno, etc.).
Estrategia 3-2-1 adaptada a contenedores
La estrategia 3-2-1 es el estándar de oro en backups. Adaptada a Docker se traduce en:
- 3 copias de los datos: la producción más dos backups. Una copia en el mismo servidor para recuperación rápida, y otra en un destino remoto.
- 2 medios diferentes: por ejemplo, disco local del servidor y almacenamiento en la nube (S3, Backblaze B2, etc.). Nunca dos copias en el mismo disco físico.
- 1 copia offsite (nube): un backup fuera del centro de datos. Si arde el datacenter, tu copia en S3 de Frankfurt sigue intacta.
Además, automatiza la rotación. Mantener infinitos backups consume espacio y dinero. Una política de retención de 7 días locales y 30 días en remoto suele ser suficiente para la mayoría de pymes.
Script de backup automatizado (Bash)
Este script hace backup de todos los volúmenes Docker, comprime con gzip, rota los backups locales y sube el resultado a un bucket S3-compatible. Guárdalo como /usr/local/bin/docker-backup.sh y ejecútalo con cron.
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/backup/docker"
S3_BUCKET="s3://mi-bucket-backups/docker"
RETENTION_DAYS=7
HEALTHCHECK_URL="https://hc-ping.com/tu-uuid-aqui"
mkdir -p "$BACKUP_DIR"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="$BACKUP_DIR/backup_${TIMESTAMP}.log"
exec > >(tee -a "$LOG_FILE") 2>&1
echo "[$(date)] Iniciando backup de volúmenes Docker..."
# Backup de cada volumen Docker
for VOLUME in $(docker volume ls -q); do
SAFE_NAME=$(echo "$VOLUME" | tr '/' '_')
ARCHIVE="$BACKUP_DIR/${SAFE_NAME}_${TIMESTAMP}.tar.gz"
echo "[$(date)] Backupeando volumen: $VOLUME"
docker run --rm \
-v "$VOLUME":/data \
-v "$BACKUP_DIR":/backup \
alpine:latest \
tar czf "/backup/$(basename "$ARCHIVE")" -C /data .
done
# Rotación: eliminar backups locales con más de 7 días
find "$BACKUP_DIR" -maxdepth 1 -name '*.tar.gz' -mtime +$RETENTION_DAYS -delete
find "$BACKUP_DIR" -maxdepth 1 -name '*.log' -mtime +$RETENTION_DAYS -delete
echo "[$(date)] Subiendo backups a S3..."
aws s3 sync "$BACKUP_DIR" "$S3_BUCKET" --exclude "*" --include "*.tar.gz"
echo "[$(date)] Backup completado."
curl -fsS -m 10 --retry 5 "$HEALTHCHECK_URL" || true
El script usa una imagen alpine temporal para leer el volumen y crear un tar.gz comprimido. Como el contenedor se ejecuta con --rm, no deja residuos. La rotación elimina automáticamente los archivos más antiguos para evitar que el disco se llene.
Restauración en minutos, no en horas
El objetivo de un backup no es hacerlo: es poder restaurarlo rápido cuando todo falla. Con este método la restauración se reduce a cuatro pasos:
- Parar el contenedor que usa el volumen:
docker stop nombre-contenedor - Restaurar el volumen desde el tar.gz:
docker run --rm -v volumen:/data -v /backup:/backup alpine tar xzf /backup/volumen_20260430_030000.tar.gz -C /data - Arrancar el contenedor de nuevo:
docker start nombre-contenedor - Verificar funcionamiento: accede a la aplicación, revisa logs, haz una prueba de escritura en la base de datos si aplica.
En un escenario real, si tienes un docker-compose.yml, puedes incluso automatizar la restauración con un script que pare los servicios, restaure los volúmenes y levante todo de nuevo. Lo importante es haberlo probado antes del desastre.
Monitorización del backup (alerta si falla)
Un backup que falla en silencio es peor que no tener backup. Necesitas saber si algo va mal antes de que lo necesites. Aquí tienes dos mecanismos sencillos:
- Healthchecks.io: Es un servicio gratuito que te da una URL única. Tu script hace un
curlal finalizar. Si no recibe el ping en el intervalo esperado, te envía un email o notificación. El script de arriba ya lo incluye. - Log de errores: El script redirige toda la salida a un fichero de log con fecha. Revisa estos logs semanalmente, o mejor, configura
logwatchologrotatepara que te alerte si aparecen errores.
Si usas AWS S3, también puedes activar notificaciones de eventos para que te avisen cuando no llegan nuevos objetos en 24 horas. La redundancia en las alertas nunca está de más.
Implementar esta estrategia no lleva más de una hora, pero puede salvarte días de trabajo y miles de euros en pérdida de datos. Si gestionas contenedores en producción, el backup no es opcional: es parte de la infraestructura.