Introduction
Ce guide pratique explique comment sauvegarder et restaurer images, volumes et configuration Docker à l’aide d’exemples concrets, prêts à copier‑coller. Vous obtiendrez un flux de bout en bout, des bonnes pratiques modernes, des exemples approfondis (y compris pour les bases de données) et un exercice clair de reprise que vous pouvez exécuter sur un hôte vierge. À la fin, vous aurez une méthode reproductible utilisable sur un portable et extensible en production.
Prérequis et hypothèses
- Hôte Linux avec Docker Engine 20.10+ (24.x recommandé) et Docker Compose v2
- Shell avec bash, GNU tar et sha256sum disponibles
- Utilisateur dans le groupe docker (ou utilisez sudo avant les commandes docker)
- Au moins 2× la taille de vos données libres sur la cible de sauvegarde
- Optionnel mais recommandé : chiffrement (age, gpg ou openssl) et stockage hors site/objet
- Images épinglées par tag ou digest (évitez latest) et fichiers Compose suivis dans git
Astuce : utilisez une VM (machine virtuelle) neuve ou un contexte Docker Desktop pour tester les restaurations en toute sécurité.
Aperçu du flux de travail
- Inventorier ce qu’il faut protéger
- Images et tags ou digests exacts
- Définitions des conteneurs (fichiers Compose, Dockerfiles, fichiers env)
- Volumes et bind mounts qui contiennent l’état
- Bases de données dans des conteneurs (faire des dumps logiques, pas des copies brutes de fichiers)
- Secrets et clés (stocker séparément ou chiffrer)
- Mise au repos ou snapshot
- Mettre les applis en mode maintenance ou planifier une courte indisponibilité pour arrêter/pauser les écritures
- Pour les bases : utiliser des dumps logiques (pg_dump, mysqldump) ou des snapshots de stockage conçus pour la cohérence
- Sauvegarder
- Config : fichiers gérés par git, plus un export « lock » de Compose résolu
- Images : docker save vers une archive tar
- Volumes : tar via un conteneur utilitaire temporaire
- Bases de données : dumps vers des fichiers stockés avec la sauvegarde
- Stocker et protéger
- Créer des sommes de contrôle (sha256)
- Chiffrer au repos et en transit
- Conserver des copies hors site avec rétention versionnée et politiques de cycle de vie
- Valider
- Tester une restauration sur un hôte propre
- Vérifier la santé des conteneurs, les checksums des données, les logs et les endpoints applicatifs
- Automatiser
- Scripts shell ou Makefile avec logs clairs et retours non nuls en cas d’échec
- Planifier via cron, timers systemd ou exécuteurs CI/CD
- Documenter le rollback
- Étapes exactes pour revenir à une sauvegarde connue, qui approuve et comment vérifier le succès
Carte rapide des artefacts
| Artefact | Comment sauvegarder | Comment vérifier |
|---|---|---|
| Images | docker save -o images.tar repo:tag | sha256sum -c images.tar.sha256; docker load -i images.tar |
| Volumes | Tar depuis un conteneur utilitaire | sha256sum -c volume.sha256; tar tzf volume.tar.gz |
| Config Compose | docker compose config > compose.lock.yaml | Diff avec l’attendu; suivi dans git |
| Dumps BD | pg_dump/mysqldump vers des fichiers | Inspecter les en-têtes; tester l’import dans une BD temporaire |
Sauvegardes pratiques (copier‑coller)
L’exemple sauvegarde un simple site Nginx qui sert du contenu depuis un volume nommé. Adaptez le modèle à vos services.
Mettre en place un service de démonstration
# Réseau et volume
docker network create appnet
docker volume create webdata
# Exécuter Nginx épinglé à une étiquette (évitez latest)
docker run -d --name web \
--network appnet -p 8080:80 \
-v webdata:/usr/share/nginx/html:rw \
nginx:1.25
# Placer du contenu d’exemple dans le volume
docker run --rm -v webdata:/data alpine \
sh -c "echo 'Hello from backup demo' > /data/index.html"
Sauvegarder le volume avec un conteneur utilitaire
set -euo pipefail
mkdir -p backups
STAMP=$(date +%F_%H%M%S)
VOL_ARCHIVE="backups/webdata-$STAMP.tar.gz"
VOL_SUM="${VOL_ARCHIVE}.sha256"
TMP_VOL_ARCHIVE="${VOL_ARCHIVE}.tmp"
# Montage en lecture seule du volume; préserve propriétaires/permissions
docker run --rm \
-v webdata:/data:ro \
-v "$(pwd)/backups":/backup \
alpine sh -c "tar --numeric-owner -czf /backup/$(basename \"$TMP_VOL_ARCHIVE\") -C /data ."
mv "$TMP_VOL_ARCHIVE" "$VOL_ARCHIVE"
sha256sum "$VOL_ARCHIVE" > "$VOL_SUM"
Pour les bind mounts sur l’hôte, préférez rsync -aHAX pour préserver les métadonnées, ou archivez le répertoire directement avec tar depuis l’hôte.
Sauvegarder l’image (restaurer sans pull)
IMG_ARCHIVE="backups/nginx-1.25-images-$STAMP.tar"
TMP_IMG_ARCHIVE="${IMG_ARCHIVE}.tmp"
docker pull nginx:1.25
docker save -o "$TMP_IMG_ARCHIVE" nginx:1.25
mv "$TMP_IMG_ARCHIVE" "$IMG_ARCHIVE"
sha256sum "$IMG_ARCHIVE" > "${IMG_ARCHIVE}.sha256"
Sauvegarder la définition de conteneur et Compose
# Capturer l’inspect du conteneur en cours d’exécution (ports, montages, env)
docker inspect web > "backups/web-$STAMP.inspect.json"
# Si vous utilisez Compose, exporter une config résolue (exécuter dans le répertoire du projet)
# docker compose config > "backups/compose-$STAMP.lock.yaml"
Optionnel : dumps de base de données (Postgres et MySQL)
# Exemple de dump logique Postgres
# export PGPASSWORD=yourpassword
# docker exec -e PGPASSWORD=$PGPASSWORD pg \
# pg_dump -U $PGUSER -h localhost -F c -f /tmp/db.dump $PGDATABASE
# docker cp pg:/tmp/db.dump "backups/pg-$STAMP.dump"
# Exemple de dump logique MySQL
# docker exec mysql \
# sh -c 'mysqldump -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE > /tmp/db.sql'
# docker cp mysql:/tmp/db.sql "backups/mysql-$STAMP.sql"
Bonne pratique : écrire le dump vers un chemin temporaire, puis ne déplacer vers le nom final qu’après succès pour éviter les artefacts partiels.
Restauration pratique et vérification
Commencez toujours par restaurer sur un hôte propre ou une VM jetable. Traitez cela comme un exercice de reprise après sinistre.
Charger les images
# Vérifier puis charger l’image sauvegardée
sha256sum -c backups/nginx-1.25-images-*.tar.sha256
IMG_TAR=$(ls -1 backups/nginx-1.25-images-*.tar | tail -n1)
docker load -i "$IMG_TAR"
Recréer et restaurer le volume
# Créer le volume cible
NEW_VOL=webdata
docker volume create "$NEW_VOL"
# Choisir la dernière archive et vérifier
sha256sum -c backups/webdata-*.sha256
VOL_ARCHIVE=$(ls -1 backups/webdata-*.tar.gz | tail -n1)
# Extraire dans le volume vide
docker run --rm \
-v "$NEW_VOL":/data \
-v "$(pwd)/backups":/backup \
alpine sh -c "cd /data && tar xzf /backup/$(basename \"$VOL_ARCHIVE\")"
Démarrer le conteneur et valider
docker run -d --name web-restore \
-p 8080:80 \
-v "$NEW_VOL":/usr/share/nginx/html \
nginx:1.25
# Vérification de base
curl -fsS http://localhost:8080 | tee /tmp/page.html
grep -q "Hello from backup demo" /tmp/page.html && echo "OK" || (echo "FAIL"; exit 1)
# Vérifications plus poussées (optionnel) : logs et santé du conteneur
docker logs --tail=50 web-restore
Si vous utilisez Compose, restaurer avec la config verrouillée
# Dans le répertoire du projet qui contient compose-$STAMP.lock.yaml
# docker compose -f backups/compose-$STAMP.lock.yaml up -d
# docker compose ps
Exercice de reprise après sinistre : pas à pas
Exécutez ceci chaque trimestre (ou après des changements significatifs) et relevez les durées pour valider RTO/RPO.
- Provisionner une VM propre ou un contexte Docker avec suffisamment d’espace disque.
- Copier l’ensemble de la sauvegarde la plus récente (images, archives de volumes, dumps BD, lock Compose, checksums).
- Vérifier les checksums de tous les artefacts avec
sha256sum -c. docker loaddes images; confirmer que les tags/digests correspondent aux attentes.- Créer des volumes nommés neufs; ne jamais restaurer dans un volume déjà utilisé.
- Restaurer les archives des volumes à l’aide d’un conteneur utilitaire.
- Recréer les secrets/fichiers d’environnement (déchiffrer si nécessaire) et valider les permissions.
- Démarrer les services (Compose ou docker run) et attendre les healthchecks.
- Vérifier :
- Les endpoint(s) de l’app répondent avec le contenu ou le statut attendu.
- Les logs sont exempts d’erreurs répétées.
- Intégrité basique des bases (p. ex., exécuter
SELECT COUNT(*)sur des tables clés oumysqlcheck).
- Documenter les commandes exactes, les durées et les résultats. Corriger les écarts avant le prochain exercice.
Plan pilote local
- Périmètre : un service Nginx avec un volume nommé.
- Artefacts : tar d’image, tar.gz du volume, JSON d’inspect, lock Compose (si utilisé), checksums.
- Critères de succès : RTO < 5 minutes sur un portable; validation des checksums; texte de la page d’accueil conforme.
- Étapes :
- Mettre en place le script de sauvegarde à partir des exemples.
- Planifier une tâche cron quotidienne écrivant dans ./backups.
- Effectuer une restauration sur une VM neuve ou un contexte Docker Desktop.
- Consigner le processus, les durées et les résultats dans votre runbook.
- Prochaine itération : ajouter un petit conteneur Postgres avec
pg_dump; encapsuler les scripts dans des cibles Make; ajouter chiffrement et synchronisation hors site.
Liste de validation et commandes utiles
- Avant sauvegarde : conteneurs sains (
docker ps), endpoints applicatifs OK (curl -fsSI), marge d’espace disque (df -h). - Contrôles d’artefacts :
sha256sumpour tous les tar; lister le contenu des tar (tar tzf backups/…tar.gz | head -n10). - Après restauration : service répond; logs propres; exécuter un smoke test ou un script d’intégration.
Modes de défaillance et remédiations
| Symptôme | Cause probable | Correctif |
|---|---|---|
tar: write error: No space left on device | Espace disque insuffisant | Libérer de l’espace ou changer la cible; vérifier avec df -h |
sha256sum: FAILED | Artefact corrompu ou partiel | Recréer/recopier; écrire dans un fichier temporaire puis renommer atomiquement |
Erreurs de permission mysqldump/pg_dump | Mauvais identifiants ou rôles | Passer les bonnes variables d’env; accorder un rôle de sauvegarde en lecture |
port already allocated | Ancien conteneur encore lié | Arrêter/supprimer l’ancien conteneur ou remapper les ports |
| Volume non vide à la restauration | Restauration dans un volume utilisé | Créer un nouveau volume; ne jamais mélanger anciennes et nouvelles données |
| Permission refusée sur un bind mount | SELinux/AppArmor ou permissions hôte | Utiliser :z/:Z pour SELinux; corriger la propriété; préférer les volumes nommés |
docker load tar invalide | Mauvais fichier ou transfert tronqué | Valider la checksum; recopier depuis la source |
| Boucle de crash après restauration | Env/secret manquant ou incompatibilité de versions | Restaurer env/secrets; assurer la compatibilité image/données |
Planification du rollback et précautions
- Conserver au moins 3 jeux de sauvegarde récents par service; étiqueter avec horodatage, environnement et commit git de l’app.
- Épingler les images à des tags immuables ou digests pour que le rollback soit déterministe.
- Ne jamais revenir en arrière sur une base de données sans considérer les migrations de schéma; garder un dump logique à jour et tester la compatibilité.
- Pendant le rollback, arrêter d’abord les workloads, restaurer l’ensemble connu-bon, puis démarrer et valider avant de rouvrir le trafic.
- Conserver les secrets en dehors des sauvegardes générales ou les chiffrer; tester régulièrement le déchiffrement.
Exemple :
# Arrêter la version défaillante
docker compose down # ou : docker stop <containers>
# Restaurer les artefacts précédents (images et volumes) comme dans la section restauration
# Démarrer explicitement des images connues-bonnes
docker run -d --name app \
-v appdata:/var/lib/app \
myorg/app:1.2.3
# Pour Compose, épingler et démarrer
docker compose -f compose-rollback.lock.yaml up -d
Exemples d’automatisation
Planification cron (quotidien à 02:15) :
# Éditer avec : crontab -e
15 2 * * * cd /opt/myapp && ./backup.sh >> backup.log 2>&1
Cibles Makefile simples :
backup:
@./scripts/backup.sh
restore-latest:
@./scripts/restore.sh latest
verify:
@./scripts/verify.sh
clean-old:
@find backups -type f -mtime +30 -delete
Assurez-vous que les scripts utilisent set -euo pipefail, retournent un code non nul en cas d’échec et stockent les logs avec les artefacts. Envisagez un timer systemd ou des planifications CI/CD pour une visibilité centralisée.
Notes pour plateformes apparentées
- Docker Compose : valider dans git; créer un lock Compose via
docker compose config; le sauvegarder avec checksums. Utiliser des healthchecks et des versions épinglées. - Kubernetes : sauvegarder les manifestes (git), utiliser des snapshots CSI de volume ou des dumps logiques de BD, et tester les restaurations dans un namespace séparé. Valider que les Deployments se déploient et que les Pods passent en Ready.
- CI/CD : exécuter les scripts de sauvegarde dans un pipeline planifié, stocker les artefacts dans votre stockage objet et garder les identifiants dans des variables protégées avec rotation.
Conclusion
Les sauvegardes ne comptent que si les restaurations fonctionnent. Vous disposez maintenant d’un flux pragmatique, orienté opérateur, pour sauvegarder et restaurer images, volumes et configuration Docker, plus un exercice propre de reprise que vous pouvez exécuter dès aujourd’hui. Commencez petit, épinglez les versions ou digests d’images, ajoutez checksums et chiffrement, et pratiquez une restauration complète sur un hôte vierge. En passant à des piles Compose ou à Kubernetes, les mêmes principes s’appliquent : inventorier l’état, mettre au repos, sauvegarder, valider et documenter le rollback.