11 KiB
Migration Automatique des Migrations - Déploiement Portainer
📋 Résumé
Ce document décrit les modifications apportées pour que les migrations de base de données s'exécutent automatiquement au démarrage du container backend, aussi bien en local (Docker Compose) qu'en production (Portainer).
✅ Problème Résolu
Avant : Les migrations devaient être exécutées manuellement avec npm run migration:run, ce qui n'était pas possible dans un environnement de production Portainer.
Après : Les migrations s'exécutent automatiquement au démarrage du container backend, avant le lancement de l'application NestJS.
🔧 Modifications Techniques
1. Nouveau Script de Démarrage (apps/backend/startup.js)
Créé un script Node.js qui :
- Attend que PostgreSQL soit prêt (retry avec timeout)
- Exécute automatiquement les migrations via TypeORM
- Démarre l'application NestJS
Fichier : apps/backend/startup.js
// Attend PostgreSQL (30 tentatives max)
async function waitForPostgres() { ... }
// Exécute les migrations TypeORM
async function runMigrations() {
const AppDataSource = new DataSource({
type: 'postgres',
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT, 10),
username: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
entities: [...],
migrations: [...],
});
await AppDataSource.initialize();
await AppDataSource.runMigrations();
}
// Démarre NestJS
function startApplication() {
spawn('node', ['dist/main'], { stdio: 'inherit' });
}
2. Modification du Dockerfile
Fichier : apps/backend/Dockerfile
Avant :
CMD ["node", "dist/main"]
Après :
# Copy startup script (includes migrations)
COPY --chown=nestjs:nodejs startup.js ./startup.js
CMD ["node", "startup.js"]
3. Variables d'environnement ajoutées
Fichier : docker/portainer-stack.yml
Ajout des variables manquantes pour le backend :
environment:
# API
API_PREFIX: api/v1
# Database
DATABASE_SYNC: false
DATABASE_LOGGING: false
# Redis
REDIS_DB: 0
# JWT
JWT_ACCESS_EXPIRATION: 15m
JWT_REFRESH_EXPIRATION: 7d
# CORS - Ajout de l'API backend dans les origines
CORS_ORIGIN: https://app.preprod.xpeditis.com,https://www.preprod.xpeditis.com,https://api.preprod.xpeditis.com
# Security
BCRYPT_ROUNDS: 10
SESSION_TIMEOUT_MS: 7200000
# Rate Limiting
RATE_LIMIT_TTL: 60
RATE_LIMIT_MAX: 100
🚀 Déploiement sur Portainer
Étape 1 : Rebuild des Images Docker
Les images Docker doivent être reconstruites avec le nouveau startup.js :
# Backend
cd apps/backend
docker build -t rg.fr-par.scw.cloud/weworkstudio/xpeditis-backend:preprod .
docker push rg.fr-par.scw.cloud/weworkstudio/xpeditis-backend:preprod
# Frontend (si nécessaire)
cd ../frontend
docker build -t rg.fr-par.scw.cloud/weworkstudio/xpeditis-frontend:preprod .
docker push rg.fr-par.scw.cloud/weworkstudio/xpeditis-frontend:preprod
Étape 2 : Mise à Jour du Stack Portainer
- Aller sur Portainer → Stacks → xpeditis-preprod
- Cliquer sur Editor
- Copier le contenu de
docker/portainer-stack.yml - Cliquer sur Update the stack
- Cocher Re-pull image and redeploy
- Cliquer sur Update
Étape 3 : Vérification des Logs
# Voir les logs du backend
docker logs xpeditis-backend -f
# Vérifier que les migrations sont exécutées
# Vous devriez voir :
# ✅ PostgreSQL is ready
# ✅ DataSource initialized
# ✅ Successfully ran X migration(s):
# - CreateAuditLogsTable1700000001000
# - CreateNotificationsTable1700000002000
# - CreateWebhooksTable1700000003000
# - ...
# ✅ Database migrations completed
# 🚀 Starting NestJS application...
📊 Migrations Exécutées Automatiquement
Lors du premier démarrage, les migrations suivantes seront exécutées :
- CreateAuditLogsTable - Table des logs d'audit
- CreateNotificationsTable - Table des notifications
- CreateWebhooksTable - Table des webhooks
- CreateInitialSchema - Schéma initial (users, organizations, carriers, ports, etc.)
- SeedOrganizations - Données de test (organisations)
- SeedCarriers - Données de test (transporteurs maritimes)
- SeedTestUsers - Utilisateurs de test :
admin@xpeditis.com(ADMIN) - Mot de passe :AdminPassword123!manager@xpeditis.com(MANAGER) - Mot de passe :AdminPassword123!user@xpeditis.com(USER) - Mot de passe :AdminPassword123!
- CreateCsvBookingsTable - Table des réservations CSV
- CreateCsvRatesTable - Table des tarifs CSV
- SeedPorts - 10 000+ ports mondiaux (UN LOCODE)
Total : ~10 migrations + seed data
⚠️ Points d'Attention
1. Base de Données Vide vs Existante
- Base vide : Toutes les migrations s'exécutent (première fois)
- Base existante : Seules les nouvelles migrations sont exécutées
- Idempotence : Les migrations peuvent être relancées sans problème
2. Temps de Démarrage
Le premier démarrage prend ~30-60 secondes :
- Attente PostgreSQL : ~10s
- Exécution migrations : ~20-40s (avec seed de 10k ports)
- Démarrage NestJS : ~5-10s
Les démarrages suivants sont plus rapides (~15-20s) car aucune migration n'est à exécuter.
3. Rollback de Migration
Si une migration échoue :
# Se connecter au container
docker exec -it xpeditis-backend sh
# Vérifier les migrations appliquées
node -e "
const { DataSource } = require('typeorm');
const ds = new DataSource({
type: 'postgres',
host: process.env.DATABASE_HOST,
port: process.env.DATABASE_PORT,
username: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
});
ds.initialize().then(async () => {
const migrations = await ds.query('SELECT * FROM migrations ORDER BY timestamp DESC LIMIT 5');
console.log(migrations);
await ds.destroy();
});
"
# Rollback dernière migration (si nécessaire)
# Attention : ceci doit être fait manuellement depuis le serveur
🔐 Sécurité
Variables d'Environnement Sensibles
Assurez-vous que les variables suivantes sont définies correctement dans Portainer :
# Base de données
DATABASE_PASSWORD: 9Lc3M9qoPBeHLKHDXGUf1 # CHANGER EN PRODUCTION
# Redis
REDIS_PASSWORD: hXiy5GMPswMtxMZujjS2O # CHANGER EN PRODUCTION
# JWT
JWT_SECRET: 4C4tQC8qym/evv4zI5DaUE1yy3kilEnm6lApOGD0GgNBLA0BLm2tVyUr1Lr0mTnV # CHANGER EN PRODUCTION
# MinIO
AWS_ACCESS_KEY_ID: minioadmin_preprod_CHANGE_ME # CHANGER EN PRODUCTION
AWS_SECRET_ACCESS_KEY: RBJfD0QVXC5JDfAHCwdUW # CHANGER EN PRODUCTION
Recommandation : Utiliser Portainer Secrets pour les mots de passe en production.
🧪 Test en Local
Pour tester avant déploiement Portainer :
# 1. Reconstruire l'image backend
cd apps/backend
docker build -t xpeditis20-backend .
# 2. Lancer le stack complet
cd ../..
docker-compose -f docker-compose.dev.yml up -d
# 3. Vérifier les logs
docker logs xpeditis-backend-dev -f
# 4. Vérifier que les tables existent
docker exec -it xpeditis-postgres-dev psql -U xpeditis -d xpeditis_dev -c "\dt"
# 5. Tester l'API
curl http://localhost:4001/api/v1/auth/login -X POST \
-H "Content-Type: application/json" \
-d '{"email":"admin@xpeditis.com","password":"AdminPassword123!"}'
📁 Fichiers Modifiés
apps/backend/
├── startup.js # ✨ NOUVEAU - Script de démarrage avec migrations
├── Dockerfile # ✏️ MODIFIÉ - CMD utilise startup.js
├── docker-entrypoint.sh # 🗑️ NON UTILISÉ (script shell alternatif)
└── run-migrations.js # 🗑️ NON UTILISÉ (script migrations standalone)
docker/
└── portainer-stack.yml # ✏️ MODIFIÉ - Ajout variables d'environnement
docker-compose.dev.yml # ✅ DÉJÀ CORRECT - Toutes les variables présentes
✅ Checklist de Déploiement
- Rebuild de l'image backend avec
startup.js - Push de l'image vers le registry Scaleway
- Mise à jour du
portainer-stack.ymlavec toutes les variables - Update du stack Portainer avec re-pull de l'image
- Vérification des logs backend (migrations exécutées)
- Test de connexion avec
admin@xpeditis.com/AdminPassword123! - Vérification que toutes les routes du dashboard fonctionnent
- Test de création d'une réservation
- Test de recherche de tarifs
- Vérification des notifications en temps réel (WebSocket)
🆘 Troubleshooting
Problème : Backend crash au démarrage
Symptôme : Container redémarre en boucle
Vérification :
docker logs xpeditis-backend --tail 100
Causes possibles :
- PostgreSQL pas prêt → Attendre 30s de plus
- Variables d'environnement manquantes → Vérifier le stack
- Migration échouée → Vérifier les logs de migration
Problème : Table "notifications" does not exist
Symptôme : Erreur 500 sur /api/v1/notifications
Cause : Migrations non exécutées
Solution :
# Redémarrer le backend pour forcer les migrations
docker restart xpeditis-backend
Problème : "Failed to connect to PostgreSQL"
Symptôme : Backend ne démarre pas après 30 tentatives
Cause : PostgreSQL pas accessible
Solution :
# Vérifier que PostgreSQL est healthy
docker ps | grep postgres
# Vérifier les logs PostgreSQL
docker logs xpeditis-db
# Tester la connexion
docker exec xpeditis-db psql -U xpeditis -d xpeditis_preprod -c "SELECT version();"
📚 Références
- Documentation TypeORM Migrations
- Docker Multi-stage Builds
- Portainer Stack Documentation
- NestJS Database
🎯 Résultat Final
✅ Migrations automatiques au démarrage du container ✅ Aucune action manuelle requise ✅ Idempotence garantie (peut être relancé) ✅ Compatible Docker Compose et Portainer ✅ Production-ready avec logs détaillés
Date de mise à jour : 2025-11-19 Version : 1.0