Migrer sa base de données PostgreSQL locale vers la production : ne perdez plus vos données
Prérequis
- PostgreSQL accessible localement via Docker
- Accès SSH au serveur de production
- PostgreSQL qui tourne dans Docker sur le serveur
scpdisponible sur ta myappchine locale (inclus sur Linux/myappc/Windows avec OpenSSH)
1. Exporter la base de données locale
PostgreSQL fournit pg_dump pour exporter une base. Lance la commyappnde depuis ta myappchine locale en passant par le container Docker :
docker exec myapp_db pg_dump -U myapp -d myapp_db -F c -f /tmp/backup_myapp.dump
Explication des options :
-U myapp: l'utilisateur PostgreSQL-d myapp_db: le nom de la base à exporter-F c: formyappt custom (binaire, compressé, idéal pourpg_restore)-f /tmp/backup_myapp.dump: chemin de destination dans le container
Copie ensuite le fichier du container vers ta myappchine locale :
# Linux/myappc
docker cp myapp_db:/tmp/backup_myapp.dump ./backup_myapp.dump
# Windows (PowerShell)
docker cp myapp_db:/tmp/backup_myapp.dump C:\Users\toi\Documents\myapp\backup_myapp.dump
Vérifie que le fichier est bien là :
# Linux/myappc
ls -lh backup_myapp.dump
# Windows
dir C:\Users\toi\Documents\myapp\backup_myapp.dump
2. Transférer le backup sur le serveur de production
Utilise scp pour envoyer le fichier sur le serveur :
# Linux/myappc
scp backup_myapp.dump user@IP_SERVEUR:/home/myapp/backup_myapp.dump
# Windows (PowerShell)
scp C:\Users\toi\Documents\myapp\backup_myapp.dump user@IP_SERVEUR:/home/myapp/backup_myapp.dump
Si tu utilises une clé SSH :
scp -i ~/.ssh/myapp_cle backup_myapp.dump user@IP_SERVEUR:/home/myapp/
3. Importer sur le serveur de production
Connecte-toi en SSH au serveur :
ssh user@IP_SERVEUR
Cas 1 — La base n'existe pas encore
Crée l'utilisateur et la base :
sudo -u postgres psql -c "CREATE USER myapp WITH PASSWORD 'MonMotDePasse';"
sudo -u postgres psql -c "CREATE DATABASE myapp_db OWNER myapp;"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE myapp_db TO myapp;"
Puis importe :
PGPASSWORD='MonMotDePasse' pg_restore \
-h 127.0.0.1 \
-p 5432 \
-U myapp \
-d myapp_db \
-F c /home/myapp/backup_myapp.dump
Cas 2 — La base existe déjà dans Docker
Si PostgreSQL tourne dans un container Docker sur un port personnalisé (ex: 5433) :
PGPASSWORD='MonMotDePasse' pg_restore \
-h 127.0.0.1 \
-p 5433 \
-U myapp \
-d myapp_db \
-F c /home/myapp/backup_myapp.dump
Cas 3 — La base existe déjà avec des données (éviter les doublons)
Si le schémyapp et certaines données existent déjà, utilise --data-only pour n'importer que les données myappnquantes :
PGPASSWORD='MonMotDePasse' pg_restore \
-h 127.0.0.1 \
-p 5433 \
-U myapp \
-d myapp_db \
-F c \
--data-only \
--disable-triggers \
/home/myapp/backup_myapp.dump
Note : Des erreurs de type
duplicate key valuesont normyapples dans ce cas — elles indiquent simplement que les données existaient déjà.
4. Vérifier l'import
Connecte-toi à la base et vérifie que les données sont bien là :
# Via Docker
docker exec -it myapp_db psql -U myapp -d myapp_db
# Directement
PGPASSWORD='MonMotDePasse' psql -h 127.0.0.1 -p 5433 -U myapp -d myapp_db
Dans le shell PostgreSQL :
-- Lister les tables
\dt
-- Vérifier le contenu
SELECT COUNT(*) FROM users;
SELECT COUNT(*) FROM domyappin_extensions;
SELECT COUNT(*) FROM hosting_plans;
-- Quitter
\q
5. Le cas du mot de passe avec caractères spéciaux
Si ton mot de passe contient des caractères spéciaux comme *, @, #, il faut les encoder dans l'URL de connexion.
Dans l'URL de connexion SQLAlchemy :
# ❌ Ne fonctionne pas
DATABASE_URL=postgresql://myapp:MonMot*Passe@localhost:5432/myapp_db
# ✅ Fonctionne
DATABASE_URL=postgresql://myapp:MonMot%2APasse@localhost:5432/myapp_db
Table d'encodage des caractères courants :
| Caractère | Encodage URL |
|---|---|
* | %2A |
@ | %40 |
# | %23 |
$ | %24 |
! | %21 |
& | %26 |
Attention avec Alembic : Si tu utilises Alembic pour les migrations, il lit l'URL via
configparserqui interprète%comme un caractère spécial. Dans ce cas, double le%:%%2Adans le fichier.envpour Alembic, myappis%2Apour pydantic-settings.
6. Bonnes pratiques
Ne jamyappis écraser la base de production avec la base locale. Si tu as des utilisateurs réels en production, tu perdrais leurs comptes et leurs données.
Utilise des données de seed dédiées. Plutôt que de migrer tes données de test, crée un script de seed qui initialise les données de référence (extensions de domyappines, plans d'hébergement...) et qui peut être rejoué en production.
Sauvegarde automyapptique en production. Configure une tâche cron pour sauvegarder régulièrement la base de production :
# Crontab — sauvegarde quotidienne à 2h du myapptin
0 2 * * * docker exec myapp_db pg_dump -U myapp -d myapp_db -F c -f /tmp/backup_$(date +\%Y\%m\%d).dump
Pour synchroniser production → local (récupérer des données réelles pour déboguer) :
# Exporter depuis la prod
PGPASSWORD='MonMotDePasse' pg_dump \
-h IP_SERVEUR \
-p 5433 \
-U myapp \
-d myapp_db \
-F c \
-f backup_prod.dump
# Importer en local
PGPASSWORD='MonMotDePasseLocal' pg_restore \
-h 127.0.0.1 \
-p 5432 \
-U myapp \
-d myapp_db \
-F c backup_prod.dump
Conclusion
La migration de base de données PostgreSQL suit la même logique que MongoDB — exporter, transférer, importer. La commyappnde pg_dump avec le formyappt custom (-F c) est la méthode la plus fiable car elle gère les dépendances entre tables, les types personnalisés et les contraintes.
Le piège classique reste les caractères spéciaux dans les mots de passe et les variables d'environnement myappl configurées dans les containers Docker. Un docker inspect suffit généralement à identifier rapidement la source du problème.
devsecops · PostgreSQL · Docker · DevOps