Docker pour les devs - 21 - Sauvegardes et restauration

pg_dump depuis un conteneur, scripts de backup automatises, sauvegarde de volumes et procedures de restauration testees.

  1. 01 Docker pour les devs - 00 - Pourquoi Docker change tout
  2. 02 Docker pour les devs - 01 - Containers vs VMs
  3. 03 Docker pour les devs - 02 - L'architecture de Docker
  4. 04 Docker pour les devs - 03 - Docker Desktop, Engine et alternatives
  5. 05 Docker pour les devs - 04 - Écrire un Dockerfile
  6. 06 Docker pour les devs - 05 - Layers et cache
  7. 07 Docker pour les devs - 06 - Le .dockerignore
  8. 08 Docker pour les devs - 07 - Multi-stage builds
  9. 09 Docker pour les devs - 08 - Choisir son image de base
  10. 10 Docker pour les devs - 09 - Docker Compose, les bases
  11. 11 Docker pour les devs - 10 - Docker Compose avance
  12. 12 Docker pour les devs - 11 - Networking Docker, les bases
  13. 13 Docker pour les devs - 12 - Networking Docker avance
  14. 14 Docker pour les devs - 13 - Volumes et persistance
  15. 15 Docker pour les devs - 14 - Variables d'environnement et secrets
  16. 16 Docker pour les devs - 15 - Permissions et utilisateurs
  17. 17 Docker pour les devs - 16 - Docker et monorepo
  18. 18 Docker pour les devs - 17 - Dev vs Prod
  19. 19 Docker pour les devs - 18 - ENTRYPOINT, CMD et scripts d'initialisation
  20. 20 Docker pour les devs - 19 - Debugger ses conteneurs
  21. 21 Docker pour les devs - 20 - Bases de donnees dans Docker
  22. 22 Docker pour les devs - 21 - Sauvegardes et restauration
  23. 23 Docker pour les devs - 22 - Conteneuriser un frontend
  24. 24 Docker pour les devs - 23 - Sécurité des conteneurs
  25. 25 Docker pour les devs - 24 - Optimisation des images
  26. 26 Docker pour les devs - 25 - Builds multi-platform
  27. 27 Docker pour les devs - 26 - Limiter les ressources de tes conteneurs
  28. 28 Docker pour les devs - 27 - Gerer les logs comme un adulte
  29. 29 Docker pour les devs - 28 - Healthchecks et restart policies
  30. 30 Docker pour les devs - 29 - Nettoyer Docker avant qu'il mange ton disque
  31. 31 Docker pour les devs - 30 - Registries et stratégie de tags
  32. 32 Docker pour les devs - 31 - Docker en CI/CD
  33. 33 Docker pour les devs - 32 - Au-dela de Compose
  34. 34 Docker pour les devs - 33 - Glossaire Docker de A a Z

21 - Sauvegardes et restauration

Ce que tu vas apprendre

  • Faire un pg_dump depuis un conteneur Docker
  • Automatiser les sauvegardes avec cron
  • Sauvegarder des volumes Docker
  • La différence entre export/import et save/load
  • Restaurer une base de donnees proprement
  • Tester ses backups (parce qu'un backup non teste n'existe pas)

Prerequisites

Avoir suivi l'article sur les bases de donnees dans Docker. Avoir PostgreSQL qui tourne dans un conteneur avec un named volume.


J'ai perdu des donnees une seule fois. C'etait un docker compose down -v un vendredi soir. Le -v supprime les volumes. J'avais tape trop vite, et la base de dev avec deux semaines de donnees de test a disparu. Depuis, je fais des backups, meme en dev.

pg_dump depuis un conteneur

La méthode la plus simple pour sauvegarder PostgreSQL :

bash# Dump SQL complet
docker exec db pg_dump -U myapp myapp_dev > backup.sql

# Dump au format custom (compresse, plus flexible pour la restauration)
docker exec db pg_dump -U myapp -Fc myapp_dev > backup.dump

# Dump avec timestamp dans le nom
docker exec db pg_dump -U myapp -Fc myapp_dev > "backup_$(date +%Y%m%d_%H%M%S).dump"

# Dump d'une seule table
docker exec db pg_dump -U myapp -t users myapp_dev > users.sql

Le format custom (-Fc) est celui que je recommande. Il est compresse, et tu peux restaurer des tables individuelles. Le format SQL brut est lisible par un humain, mais moins flexible.

Si tu veux un dump complet avec les rôles et les tablespaces :

bashdocker exec db pg_dumpall -U myapp > full_backup.sql

Automatiser avec cron

Un script de backup que j'utilise sur mes projets :

bash#!/bin/bash
set -e

BACKUP_DIR="/backups/postgres"
CONTAINER="db"
DB_USER="myapp"
DB_NAME="myapp_dev"
KEEP_DAYS=7

mkdir -p "$BACKUP_DIR"

FILENAME="$BACKUP_DIR/${DB_NAME}_$(date +%Y%m%d_%H%M%S).dump"

echo "Backup de $DB_NAME..."
docker exec "$CONTAINER" pg_dump -U "$DB_USER" -Fc "$DB_NAME" > "$FILENAME"

SIZE=$(du -h "$FILENAME" | cut -f1)
echo "Backup termine: $FILENAME ($SIZE)"

# Supprimer les backups de plus de 7 jours
find "$BACKUP_DIR" -name "*.dump" -mtime +$KEEP_DAYS -delete
echo "Anciens backups nettoyes (plus de $KEEP_DAYS jours)"

Et la crontab :

bash# Backup tous les jours a 3h du matin
0 3 * * * /home/deploy/scripts/backup-db.sh >> /var/log/backup.log 2>&1

Sur paltemps.fr, le script tourne une fois par jour et garde les 7 derniers jours. Pour un side project c'est largement suffisant. Pour de la prod serieuse, tu veux aussi envoyer les backups sur un stockage distant (S3, GCS).

Sauvegarder des volumes Docker

Parfois tu veux sauvegarder le volume entier, pas juste la base. La technique classique :

bash# Sauvegarder un volume dans une archive tar
docker run --rm \
  -v pgdata:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/pgdata_backup.tar.gz -C /source .

# Restaurer depuis l'archive
docker run --rm \
  -v pgdata:/target \
  -v $(pwd):/backup \
  alpine sh -c "cd /target && tar xzf /backup/pgdata_backup.tar.gz"

Le principe : on lance un conteneur Alpine temporaire qui a acces au volume (/source) et au dossier local (/backup), et on fait un tar. C'est générique, ca marche pour n'importe quel volume.

docker cp : copier des fichiers

Pour des fichiers individuels :

bash# Copier depuis le conteneur vers l'hote
docker cp db:/var/lib/postgresql/data/pg_hba.conf ./pg_hba.conf

# Copier depuis l'hote vers le conteneur
docker cp ./mon-script.sql db:/tmp/mon-script.sql

docker cp marche meme sur des conteneurs arretes. Pratique pour récupérer des logs ou des fichiers de config apres un crash, comme on l'a vu dans l'article sur le debug.

export/import vs save/load

Deux paires de commandes qui font des choses différentes :

bash# export/import : filesystem d'un CONTENEUR (pas les metadonnees)
docker export mon-conteneur > conteneur.tar
docker import conteneur.tar nouvelle-image:v1

# save/load : IMAGE complete (layers, metadonnees, tags)
docker save mon-image:v1 > image.tar
docker load < image.tar

export/import aplatit toutes les couches en une seule. Tu perds l'historique des layers, les variables d'environnement, le CMD. C'est utile pour transférer un filesystem, pas pour sauvegarder une image.

save/load garde tout intact. C'est ce que tu utilises pour deplacer une image entre machines sans passer par un registry. Par exemple, envoyer une image sur un serveur sans Docker Hub :

bashdocker save mon-app:v2 | gzip > mon-app-v2.tar.gz
scp mon-app-v2.tar.gz deploy@server:/tmp/
ssh deploy@server "docker load < /tmp/mon-app-v2.tar.gz"

Procedure de restauration

Le backup ne vaut rien si tu ne testes pas la restauration. Voici comment restaurer :

bash# Restauration depuis un dump SQL
docker exec -i db psql -U myapp myapp_dev < backup.sql

# Restauration depuis un dump custom
docker exec -i db pg_restore -U myapp -d myapp_dev --clean --if-exists < backup.dump

# Restauration dans une base neuve
docker exec db createdb -U myapp myapp_restored
docker exec -i db pg_restore -U myapp -d myapp_restored < backup.dump

Le --clean --if-exists supprime les objets existants avant de les recreer. Sans ca, tu auras des erreurs "already exists" partout.

Pour Redis, c'est plus simple. Si tu as active la persistance AOF ou RDB :

bash# Le fichier est dans le volume
docker cp redis:/data/dump.rdb ./redis-backup.rdb

# Pour restaurer, copie le fichier et redemarre
docker cp ./redis-backup.rdb redis:/data/dump.rdb
docker restart redis

Tester ses backups

J'ai un script qui teste la restauration automatiquement :

bash#!/bin/bash
set -e

BACKUP_FILE=$1

echo "Test de restauration de $BACKUP_FILE..."

# Lancer un PostgreSQL temporaire
docker run -d --name test-restore \
  -e POSTGRES_USER=myapp \
  -e POSTGRES_PASSWORD=test \
  -e POSTGRES_DB=test_restore \
  postgres:16-alpine

# Attendre que PostgreSQL soit pret
sleep 5

# Restaurer le backup
docker exec -i test-restore pg_restore \
  -U myapp -d test_restore --clean --if-exists < "$BACKUP_FILE"

# Verifier qu'il y a des donnees
COUNT=$(docker exec test-restore psql -U myapp -d test_restore -t -c "SELECT count(*) FROM information_schema.tables WHERE table_schema = 'public'")
echo "Tables trouvees: $COUNT"

# Nettoyer
docker rm -f test-restore

echo "Test de restauration reussi."

Fais tourner ce script apres chaque backup automatique. Un backup que tu n'as jamais teste, c'est un fichier qui prend de la place pour rien.

Résumé

  • pg_dump -Fc donne un backup compresse et flexible a restaurer.
  • Un script cron avec rotation des fichiers gere les backups quotidiens.
  • Les volumes se sauvegardent avec un conteneur Alpine temporaire et tar.
  • save/load pour les images, export/import pour les filesystems de conteneurs.
  • pg_restore --clean --if-exists restaure proprement sur une base existante.
  • Teste tes backups. Toujours.

Article précédent : Docker 20 - Bases de donnees Article suivant : Docker 22 - Frontend

Sources

Réservez un audit gratuit de 30 minutes. Je vous montre concrètement ce qu'on peut automatiser.