
695 - Como evito sustos con Docker (y tu deberías hacerlo también)
rubadb es un contenedor #docker con el que crear #backup y copias de seguridad de bases de datos y volumenes docker de forma sencilla y programada
Me aterra la posibilidad de encontrarme un día con la desagradable sorpresa de haber perdido toda la información que tengo en atareao.es. Esto me ha llevado a buscar distintas soluciones para intetar evitar que esto se vuelva una realidad, y como ya te puedes imaginar, una de las estrategias que he implementado ha sido el uso de backups o copias de seguridad. Inicialmente la solución recaía en el proveedor del hosting, sin embargo, con el paso del tiempo, esto ha ido cambiando, pasando, al principio por soluciones mas manuales, para convertirse en procesos automáticos conforme he ido adquiriendo los suficientes conocimientos para hacerlo.

Como evito sustos con Docker (y tu deberías hacerlo también)
Un paseo por le pasado
No es, ni mucho menos, la primera vez que hablo de esto de realizar copias de seguridad, en particular de Docker. En concreto, en el episodio 441 sobre Backups en Docker te comenté como realizar copias de seguridad de volumenes docker, en el 605 te hable sobre como realizar [migraciones y backup de volumenes Docker], y ya introduje las copias de seguridad de bases de datos como MariaDB, y para completar el círculo, en el episodio 677 te hablé de como evitar perder tus datos con Backups infalibles.
En este tiempo he utilizado distintos medios y sistemas para realizar backup de volumenes Docker y de bases de datos, en general siempre sobre Docker. Pero, gracias a Restic y posteriormente a Rustic, he implementado una solución solida y fiable.
Perfecto, gracias por compartirlo. A continuación te presento la nueva escaleta del episodio del podcast «Atareao con Linux» de 20 minutos, donde introduces tu herramienta rubadb como solución automatizada para realizar copias de seguridad de volúmenes Docker y bases de datos, incluyendo un ejemplo de uso con docker-compose
y un Dockerfile
personalizado.
¿Que tenemos que respaldar?
Una de las preguntas mas recurrentes a la hora de hacer copias de seguridad es ¿que tengo que respaldar?. En general el planteamiento es sencillo, pero la respuesta no tanto. En el caso de Docker, lo que tenemos que respaldar son los volúmenes, y en particular aquellos que contienen datos persistentes de servicios como bases de datos, Nextcloud, etc. En el caso de las bases de datos, como MariaDB o PostgreSQL, es recomendable hacer copias de seguridad consistentes.
Incluso, si quisieras tendrías que hacer una copia de seguridad de tus archivos de configuración, o incluso una copia de seguridad de los archivos de configuración del sistema que has modificado para personalizar la instalación a tus necesidades.
Pero, en ningún caso, deberías hacer copia de seguridad de los archivos del sistema operativo. Esta parte se la deberías de dejar a los snapshot.
¿Como hacer copias de seguridad en Docker?
Actualmente estoy utilizando rustic, como herramienta para hacer las copias de seguridad de mis datos mas importantes, pero no lo estaba haciendo para el caso de Docker.
Sin embargo, en algunos otros episodios ya hablé sobre como podías hacer esas copias de seguridad, utilizando comandos como docker cp
, o incluso utilizando tar
para hacer copias de seguridad de los volúmenes Docker. Mientras, que en el caso de las bases de datos, lo que hacía era utilizar los comandos mysqldump
o pg_dump
para hacer las copias de seguridad.
Sin embargo, esto de hacerlo a mano está sujeto a errores humanos, y no es una solución fiable ni mucho menos. Por ejemplo, yo tiendo a olvidar cuando tengo que hacer la copia de seguridad. Esto me llevó en su momento a buscar soluciones automatizadas.
Automatización con rubadb
rubadb es una combinación de herramientas que están contenerizadas, y que te van a permitir realizar copias de seguridad de tus volumenes docker y de tus bases de datos, pero además de forma completamente automatizada. Solo tienes que programar cuando quieres que se haga y compartir los archivos de configuración.
Se trata de una herramienta sencilla, pero con todo lo necesario para que esto de las copias de seguridad pase a un segundo plano,
- Fácil integración en entornos Docker.
- Soporte para PostgreSQL y MariaDB.
- Tareas programadas con
cron
. - Integración directa con herramientas como
rustic
para respaldo cifrado.
Un ejemplo de docker-compose
services:
postgresql_db:
image: postgres
container_name: postgresql_db
restart: unless-stopped
init: true
environment:
POSTGRES_USER: "$POSTGRES_USER"
POSTGRES_PASSWORD: "$POSTGRES_PASSWORD"
POSTGRES_DB: "$POSTGRES_DB"
volumes:
- pgdata:/var/lib/postgresql/data
ports:
- 5432:5432
healthcheck:
test: ["CMD-SHELL", "sh -c 'pg_isready -U $POSTGRES_USER -d $POSTGRES_DB'"]
interval: 1s
timeout: 5s
retries: 10
rubadb:
image: atareao/rubadb
container_name: rubadb
restart: always
init: true
environment:
SCHEDULE: "0 3 * * *"
POSTGRESQL_HOST: postgresql_db
POSTGRESQL_PORT: 5432
POSTGRESQL_USER: "$POSTGRES_USER"
POSTGRESQL_PASS: "$POSTGRES_PASSWORD"
volumes:
- backup_db:/app/backup/db
- backup_local:/app/backup/local
- ./config:/app/.config/rustic
volumes:
pgdata: {}
backup_db: {}
backup_local: {}
Como ves es un docker-compose
sencillo, pero que incluye todo lo necesario para hacer copias de seguridad de tus bases de datos. En este caso, de PostgreSQL, pero también puedes hacerlo con MariaDB. En la primera parte encuentras la base de datos y en la segunda parte el servicio de rubadb
, que es el que se encarga de hacer las copias de seguridad. Allí está definido, las variables de entorno que necesitas para conectarte a la base de datos, y el volumen donde se van a almacenar las copias de seguridad. Y también la variable SCHEDULE
, que es la que se encarga de programar las copias de seguridad. En este ejemplo la copia de seguridad se realizará todos los días a las 3 de la mañana.
Mientras que en el directorio ./config
, es necesario que incluyas todos los archivos de configuración correspondientes a los repositorios donde quieras que se guarden esas copias de seguridad.
Un ejemplo de un archivo de configuración de rustic
para el caso de PostgreSQL sería el siguiente:
[repository]
repository = "/app/backup/local"
password = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
[forget]
keep-daily = 7
keep-weekly = 4
keep-monthly = 6
[[backup.snapshots]]
sources = ["/app/backup/db"]
[backup.snapshots.hooks]
run-after = ['curl -X "POST" "https://openobserve.tuservidor.es/api/default/archi_backup/_json" -H "accept: application/json" -H "Authorization: Basic XXXXXXXXXXXXXX" -H "Content-Type: application/json" -d "[{\"repository\": \"local\", \"action\": \"backup\", \"ok\": \"true\"}]"']
run-failed = ['curl -X "POST" "https://openobserve.tuservidor.es/api/default/archi_backup/_json" -H "accept: application/json" -H "Authorization: Basic XXXXXXXXXXXXXX" -H "Content-Type: application/json" -d "[{\"repository\": \"local\", \"action\": \"backup\", \"ok\": \"false\"}]"']
Este configura una copia de seguridad en local, en concreto en el volumen /app/backup/local
, y además establece la política de persistencia de copias de seguridad. A parte de esto, realiza una llamada a la API de OpenObserve para que sepa que se ha realizado una copia de seguridad, y el resultado de la misma.
Además de este archivo de configuración, tengo otro archivo de configuración para el caso de las copias de seguridad en remoto, que es el siguiente:
[repository]
repository = "opendal:s3"
password = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
[repository.options]
root = "/"
bucket = "rustic-backup-test"
endpoint = "https://s3.tuservidor.es"
region = "s3"
access_key_id = "XXXXXXXXXXXXXXXXXXXXXXX"
secret_access_key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
[forget]
keep-daily = 7
keep-weekly = 4
keep-monthly = 6
[[backup.snapshots]]
sources = ["/app/backup/db"]
[backup.snapshots.hooks]
un-after = ['curl -X "POST" "https://openobserve.tuservidor.es/api/default/archi_backup/_json" -H "accept: application/json" -H "Authorization: Basic XXXXXXXXXXXXXX" -H "Content-Type: application/json" -d "[{\"repository\": \"local\", \"action\": \"backup\", \"ok\": \"true\"}]"']
run-failed = ['curl -X "POST" "https://openobserve.tuservidor.es/api/default/archi_backup/_json" -H "accept: application/json" -H "Authorization: Basic XXXXXXXXXXXXXX" -H "Content-Type: application/json" -d "[{\"repository\": \"local\", \"action\": \"backup\", \"ok\": \"false\"}]"']
En este caso, la configuración incluye los parámetros necesario para guardar los datos en un servidor S3, pero, si te das cuenta, el resto de parámetros son los mismos que en el caso anterior.
- rubadb se conecta a los servicios de bases de datos definidos en el mismo
compose
. - Tareas programadas vía
cron
. - Backups almacenados en volúmenes y/o gestionados con
rustic
.
En este caso, solo he puesto un par de archivos de configuración correspondientes a dos repositorios, uno local y otro remoto, pero tu puedes poner tantos como necesites, de forma que cuando se realice la copia de seguridad se va a realizar un barrido por todos esos repositorios y se van a guardar las copias de seguridad en cada uno de ellos.
Sobre rubadb
El Dockerfile de rubadb, se encuentra dividido en dos pasos. El primero de ellos es el encargado de compilar rustic, la herramienta que utilizamos para realizar las copias de seguridad, mientras que en el segundo se instalan todas las herramientas necesarias para hacer los dump de las bases de datos y dcron, que es quien se encargará de realizar la programación.
A continuación está el script de inicio, que lo primero que hace es comprobar si los repositorios donde se van a guardar las copias de seguridad están inicializados, y en caso de que no lo estén, los inicializa. Después de esto, se configura el cron
para que realice las copias de seguridad en el momento indicado. Por último, se ejecuta el comando dcron
, que es el encargado de ejecutar las tareas programadas.
Y por último el script encargado de hacer los volcados de las bases de datos y guardarlos datos en los volúmenes correspondientes, para a continuación realizar la copia de seguridad de esos volúmenes.
Como ves, el proceso es realmente sencillo, lo que le da gran consistencia, y además, es completamente automatizado. Solo tienes que preocuparte de definir los archivos de configuración y de programar las copias de seguridad.
Rustic vs Restic
Característica | restic | rustic |
---|---|---|
Lenguaje | Go | Rust |
Compatibilidad con Repositorios | Propio (restic ) | Compatible con repositorios de restic |
Velocidad de Backup | Buena, pero puede ser lenta en repos grandes | Mejorada, especialmente en backups incrementales |
Velocidad de Restore | Aceptable | Más rápida en ciertos escenarios |
Detección de cambios | Basada en archivos | Soporte para mtree y detección precisa de cambios |
Multithreading | Limitado | Mejor aprovechamiento de núcleos múltiples |
Compresión | No | Sí (Zstandard, configurable por archivo o repo) |
Cifrado | Sí (AES-256) | Sí (igual que restic, con mejoras potenciales) |
Integridad de datos | Verificación con restic check | check mejorado y más detallado |
Snapshots incrementales | Sí | Sí, con mejoras en rendimiento y eficiencia |
Configuración granular por repo | Limitada | Muy flexible (config.json , políticas de snapshot, etc.) |
Eliminación de snapshots (prune ) | Correcta pero lenta | Más rápida y configurable con reglas |
Estado del proyecto | Estable y ampliamente usado | Activo, aún en desarrollo pero usable |
Interfaz CLI | Amigable y bien documentada | Similar, con mejoras en algunas opciones |
Soporte para Backups por Chunk | Básico | Avanzado (deduplicación más eficiente por chunking) |
Uso en Docker/CI/CD | Muy usado y probado | Compatible, en crecimiento |
Conclusión
Como te digo, se trata de una solución sencilla, donde lo único que hice es preocuparme de tener las herramientas necesarias para hacer los volcados de las bases de datos y realizar las copias de seguridad. El resto lo hace rubadb por ti. En el caso de que quieras hacer copias de seguridad de otros servicios, como Nextcloud, o incluso de archivos de configuración, solo tienes que añadir los archivos de configuración correspondientes.
Más información,