Image Docker basée sur Debian Slim pour automatiser les backups de bases de données PostgreSQL, MariaDB/MySQL et MongoDB via cron.
- Support de PostgreSQL (versions 12 à 18), MariaDB/MySQL et MongoDB
- Installation dynamique des clients au démarrage (seuls les outils nécessaires sont installés selon la config)
- Image légère : aucun client de base de données pré-installé
- Configuration flexible via fichier de configuration
- Planification des backups avec cron
- Compression automatique des dumps (gzip)
- Horodatage des fichiers de backup
- Rotation automatique des anciens backups
- Support de multiples bases de données simultanément
- Healthcheck intégré vérifiant la connectivité aux bases de données
- Logs centralisés
- Build automatique via GitHub Actions
- Images multi-architecture (amd64, arm64)
Si ce projet est hébergé sur GitHub, vous pouvez utiliser l'image directement sans avoir à la construire :
docker pull ghcr.io/greite/database-backup:latestExemple de compose.yml utilisant l'image pré-buildée :
version: '3.8'
services:
db-backup:
image: ghcr.io/greite/database-backup:latest
container_name: db-backup
restart: unless-stopped
volumes:
- ./backups:/backups
- ./backups.conf:/config/backups.conf:ro
networks:
- db-networklatest- Dernière version stable de la branche principalemain-<sha>- Version spécifique basée sur un commitv1.0.0- Version taggée (si vous créez des releases)
.
├── Dockerfile
├── compose.yml # Exemple avec bases de données de test
├── backups.conf # Configuration des backups
├── backups.conf.example # Exemple de configuration
├── GITHUB_SETUP.md # Guide de configuration GitHub Actions
├── .github/
│ └── workflows/
│ └── docker-build.yml # Workflow de build automatique
├── scripts/
│ ├── backup.sh # Script de backup principal
│ ├── entrypoint.sh # Script d'initialisation
│ └── healthcheck.sh # Script de healthcheck
└── backups/ # Répertoire des backups (créé automatiquement)
├── postgres/
│ └── myapp_db/
└── mariadb/
└── wordpress/
Le fichier backups.conf définit les backups à effectuer. Chaque ligne représente un backup avec le format suivant :
CRON_SCHEDULE|TYPE|HOST|PORT|DATABASE|USER|PASSWORD|RETENTION_DAYS|PG_VERSION
Champs :
CRON_SCHEDULE: Expression cron standard (ex:0 2 * * *pour 2h du matin chaque jour)TYPE: Type de base de données (postgres,mariadb,mysql, oumongodb)HOST: Nom d'hôte ou adresse IP du serveur de base de donnéesPORT: Port de connexion (optionnel, par défaut 5432 pour postgres, 3306 pour mariadb, 27017 pour mongodb)DATABASE: Nom de la base de données à sauvegarderUSER: Utilisateur de connexion à la base de données (optionnel pour MongoDB sans auth)PASSWORD: Mot de passe de connexion (les caractères spéciaux sont supportés, optionnel pour MongoDB sans auth)RETENTION_DAYS: Nombre de jours de rétention (optionnel, par défaut 7)PG_VERSION: Version du client PostgreSQL à utiliser - uniquement pour PostgreSQL (optionnel, valeurs possibles: 12, 13, 14, 15, 16, 17, 18, par défaut 18)
Note importante sur les mots de passe :
Les mots de passe avec caractères spéciaux (!, @, #, $, %, ^, &, *, etc.) sont entièrement supportés. Le système échappe automatiquement tous les caractères spéciaux. Vous n'avez pas besoin d'échapper ou de mettre des guillemets autour de votre mot de passe dans le fichier de configuration.
Exemples :
# Backup PostgreSQL 18 tous les jours à 2h, conserver 14 jours
0 2 * * *|postgres|db-server|5432|myapp|backup_user|SecureP@ss|14|18
# Backup PostgreSQL 15 (serveur legacy) tous les jours à 2h30, conserver 14 jours
0 2 30 * * *|postgres|pg-old-server|5432|legacy_app|backup_user|SecureP@ss|14|15
# Backup PostgreSQL sans spécifier la version (utilise v18 par défaut)
0 3 * * *|postgres|pg-new|5432|modern_app|dbuser|pass123|7
# Backup MariaDB tous les jours à 3h, conserver 7 jours
0 3 * * *|mariadb|mysql-server|3306|wordpress|wp_backup|MyPassword|7
# Backup toutes les 6 heures, conserver 3 jours
0 */6 * * *|postgres|localhost|5432|ecommerce|dbuser|pass123|3|18
# Backup tous les dimanches à minuit, conserver 30 jours
0 0 * * 0|mariadb|db.example.com||analytics|readonly|secret|30
# Exemple avec un mot de passe contenant des caractères spéciaux
0 4 * * *|postgres|pg-prod|5432|webapp|admin|ZxirfRuipZPHPc^#V#HFpCpRyrQ!zG5W|14|18
# Backup MongoDB avec authentification
0 5 * * *|mongodb|mongo-prod|27017|ecommerce|dbadmin|SecureM0ng0!|14
# Backup MongoDB sans authentification (environnement dev/test)
0 5 * * *|mongodb|localhost|27017|test_db|||7
Notes sur la version PostgreSQL :
- Le champ
PG_VERSIONn'est utilisé que pour les backups PostgreSQL - Si omis, la version 18 est utilisée par défaut
- Cela permet de sauvegarder différentes versions de PostgreSQL avec le même conteneur
- Les versions supportées sont : 12, 13, 14, 15, 16, 17, 18
Installation dynamique des clients de bases de données :
- Aucun client de base de données n'est pré-installé dans l'image Docker
- Au démarrage, le conteneur analyse la configuration et installe uniquement les outils nécessaires :
- PostgreSQL : installe les versions spécifiques configurées (12-18)
- MariaDB/MySQL : installe
mariadb-clientsi configuré - MongoDB : installe
mongodump,mongorestoreetmongoshsi configuré
- Cela réduit significativement la taille de l'image de base
- Prérequis : une connexion internet est nécessaire au premier démarrage du conteneur
- Le premier démarrage peut prendre 30-90 secondes supplémentaires selon les clients à installer
0 2 * * * # Tous les jours à 2h du matin
0 */6 * * * # Toutes les 6 heures
0 0 * * 0 # Tous les dimanches à minuit
30 1 * * * # Tous les jours à 1h30
0 0 1 * * # Le 1er de chaque mois à minuit
- Créez votre fichier
backups.conf:
cp backups.conf.example backups.conf
# Éditez backups.conf avec vos paramètres- Lancez les services :
docker-compose up -d- Vérifiez les logs :
docker-compose logs -f db-backup- Construisez l'image :
docker build -t db-backup .- Lancez le container :
docker run -d \
--name db-backup \
-v $(pwd)/backups:/backups \
-v $(pwd)/backups.conf:/config/backups.conf:ro \
db-backup- Vérifiez les logs :
docker logs -f db-backupls -lh backups/postgres/myapp_db/
ls -lh backups/mariadb/wordpress/
ls -lh backups/mongodb/ecommerce/Les backups sont organisés par type et base de données :
backups/
├── postgres/
│ └── myapp_db/
│ ├── myapp_db_20250131_020000.sql.gz
│ ├── myapp_db_20250130_020000.sql.gz
│ └── ...
├── mariadb/
│ └── wordpress/
│ ├── wordpress_20250131_030000.sql.gz
│ ├── wordpress_20250130_030000.sql.gz
│ └── ...
└── mongodb/
└── ecommerce/
├── ecommerce_20250131_050000.tar.gz
├── ecommerce_20250130_050000.tar.gz
└── ...
Note : Les backups MongoDB sont au format .tar.gz (archive BSON compressée), tandis que PostgreSQL et MariaDB utilisent .sql.gz (dump SQL compressé).
PostgreSQL :
# Décompresser et restaurer
gunzip -c backups/postgres/myapp_db/myapp_db_20250131_020000.sql.gz | \
psql -h localhost -U postgres -d myapp_dbMariaDB :
# Décompresser et restaurer
gunzip -c backups/mariadb/wordpress/wordpress_20250131_030000.sql.gz | \
mysql -h localhost -u root -p wordpressMongoDB :
# Extraire l'archive et restaurer
mkdir -p /tmp/mongo_restore
tar -xzf backups/mongodb/ecommerce/ecommerce_20250131_050000.tar.gz -C /tmp/mongo_restore
# Restaurer la base de données
mongorestore --uri="mongodb://admin:password@localhost:27017/ecommerce?authSource=admin" \
--gzip \
--drop \
/tmp/mongo_restore/ecommerce
# Nettoyer
rm -rf /tmp/mongo_restoreVous pouvez exécuter un backup manuellement sans attendre le cron :
PostgreSQL 18 :
docker exec db-backup /scripts/backup.sh \
postgres \
postgres-db \
5432 \
myapp_db \
postgres \
postgres_password \
14 \
18PostgreSQL 15 (ou autre version) :
docker exec db-backup /scripts/backup.sh \
postgres \
postgres-db \
5432 \
myapp_db \
postgres \
postgres_password \
14 \
15MariaDB :
docker exec db-backup /scripts/backup.sh \
mariadb \
mariadb-db \
3306 \
wordpress \
wp_user \
wp_password \
7MongoDB :
docker exec db-backup /scripts/backup.sh \
mongodb \
mongodb-db \
27017 \
myapp \
admin \
mongo_password \
7Support des caractères spéciaux : Le système gère automatiquement les mots de passe complexes contenant tous types de caractères spéciaux :
- Symboles :
!,@,#,$,%,^,&,*,(,),-,_,+,= - Espaces (bien que déconseillés)
- Caractères Unicode
Fonctionnement :
- Pour PostgreSQL : utilise la variable d'environnement
PGPASSWORD(méthode sécurisée recommandée) - Pour MariaDB/MySQL : utilise la variable d'environnement
MYSQL_PWD(évite l'exposition en ligne de commande) - Pour MongoDB : utilise l'URI de connexion avec authentification intégrée (password URL-encodé automatiquement)
- Les mots de passe sont automatiquement échappés avec
printf %qpour être passés en toute sécurité à travers le système cron
- Permissions des fichiers : Assurez-vous que
backups.confa des permissions restrictives car il contient des mots de passe :
chmod 600 backups.conf- Utilisateurs de backup dédiés : Créez des utilisateurs avec privilèges minimaux pour les backups :
PostgreSQL :
CREATE USER backup_user WITH PASSWORD 'secure_password';
GRANT CONNECT ON DATABASE myapp_db TO backup_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO backup_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO backup_user;MariaDB :
CREATE USER 'backup_user'@'%' IDENTIFIED BY 'secure_password';
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON myapp_db.* TO 'backup_user'@'%';
FLUSH PRIVILEGES;MongoDB :
// Se connecter à MongoDB et créer un utilisateur backup
use admin
db.createUser({
user: "backup_user",
pwd: "secure_password",
roles: [
{ role: "backup", db: "admin" },
{ role: "read", db: "myapp" }
]
})-
Stockage des backups : Considérez de monter un volume chiffré pour
/backups -
Backups externes : Synchronisez régulièrement les backups vers un stockage externe (S3, NAS, etc.)
docker-compose psLe conteneur inclut un healthcheck qui vérifie automatiquement :
- Que le daemon cron est en cours d'exécution
- Que toutes les bases de données configurées sont accessibles
- Que les connexions utilisent la bonne version du client PostgreSQL
Le healthcheck s'exécute toutes les 5 minutes avec un timeout de 30 secondes. L'état du healthcheck est visible avec :
docker inspect --format='{{.State.Health.Status}}' db-backupPour voir les détails du dernier healthcheck :
docker inspect --format='{{json .State.Health}}' db-backup | jqPour exécuter manuellement le healthcheck :
docker exec db-backup /scripts/healthcheck.shdocker-compose logs -f db-backupfind backups -name "*.sql.gz" -type f -mtime -1 -lsVérifiez que le fichier backups.conf existe :
docker-compose logs db-backup- Vérifiez la configuration cron :
docker exec db-backup cat /etc/cron.d/db-backups- Vérifiez que cron est en cours d'exécution :
docker exec db-backup ps aux | grep cron- Testez la connexion à la base de données :
# PostgreSQL - Vérifier les versions installées
docker exec db-backup ls -la /usr/lib/postgresql/
# PostgreSQL 18
docker exec db-backup /usr/lib/postgresql/18/bin/pg_dump --version
docker exec db-backup /usr/lib/postgresql/18/bin/psql -h postgres-db -U postgres -d myapp_db -c "SELECT 1"
# PostgreSQL 15 (ou autre version)
docker exec db-backup /usr/lib/postgresql/15/bin/pg_dump --version
docker exec db-backup /usr/lib/postgresql/15/bin/psql -h postgres-db -U postgres -d myapp_db -c "SELECT 1"
# MariaDB
docker exec db-backup mysqldump --version
docker exec db-backup mysql -h mariadb-db -u wp_user -p'wp_password' -e "SELECT 1"
# MongoDB
docker exec db-backup mongodump --version
docker exec db-backup mongosh "mongodb://admin:mongo_password@mongodb-db:27017/myapp?authSource=admin" --eval "db.runCommand({ping: 1})"Vérifiez que RETENTION_DAYS est bien défini dans votre configuration et que la valeur est un nombre positif.
Ajoutez dans le Dockerfile :
ENV TZ=Europe/Paris
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneModifiez scripts/backup.sh pour envoyer des notifications par email ou webhook en cas de succès ou d'échec.
Remplacez gzip par bzip2 ou xz dans scripts/backup.sh pour une meilleure compression.
Ce projet inclut un workflow GitHub Actions (.github/workflows/docker-build.yml) qui build et publie automatiquement l'image Docker sur GitHub Container Registry.
Le workflow se déclenche automatiquement sur :
- Push sur la branche
mainoumaster - Création d'un tag (ex:
v1.0.0) - Pull requests
- Déclenchement manuel via l'interface GitHub
-
Activer GitHub Container Registry : Aucune configuration nécessaire, c'est activé par défaut pour tous les repositories GitHub.
-
Rendre l'image publique (optionnel) :
- Allez sur
https://github.com/users/VOTRE_USERNAME/packages/container/REPO_NAME/settings - Changez la visibilité de "Private" à "Public"
- Allez sur
Pour créer une nouvelle version taggée :
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0Cela créera automatiquement les tags Docker suivants :
ghcr.io/username/repository:v1.0.0ghcr.io/username/repository:1.0ghcr.io/username/repository:1ghcr.io/username/repository:latest
- Allez dans l'onglet "Actions" de votre repository GitHub
- Sélectionnez le workflow "Build and Push Docker Image"
- Vérifiez que le build a réussi
- L'image sera disponible dans la section "Packages" de votre repository
Une fois l'image publiée, remplacez dans votre compose.yml :
# Avant (build local)
services:
db-backup:
build: .
# Après (utiliser l'image pré-buildée)
services:
db-backup:
image: ghcr.io/username/repository:latestMIT