# Guide de Déploiement Portainer - Xpeditis Ce guide explique comment déployer les stacks Xpeditis (staging et production) sur Portainer avec Traefik. --- ## 📋 Prérequis ### 1. Infrastructure Serveur - **Serveur VPS/Dédié** avec Docker installé - **Minimum**: 4 vCPU, 8 GB RAM, 100 GB SSD - **Recommandé Production**: 8 vCPU, 16 GB RAM, 200 GB SSD - **OS**: Ubuntu 22.04 LTS ou Debian 11+ ### 2. Traefik déjà déployé - Network `traefik_network` doit exister - Let's Encrypt configuré (`letsencrypt` resolver) - Ports 80 et 443 ouverts ### 3. DNS Configuré **Staging**: - `staging.xpeditis.com` → IP du serveur - `api-staging.xpeditis.com` → IP du serveur **Production**: - `xpeditis.com` → IP du serveur - `www.xpeditis.com` → IP du serveur - `api.xpeditis.com` → IP du serveur ### 4. Images Docker Les images Docker doivent être buildées et pushées sur un registry (Docker Hub, GitHub Container Registry, ou privé): ```bash # Build backend cd apps/backend docker build -t xpeditis/backend:staging-latest . docker push xpeditis/backend:staging-latest # Build frontend cd apps/frontend docker build -t xpeditis/frontend:staging-latest . docker push xpeditis/frontend:staging-latest ``` --- ## 🚀 Déploiement sur Portainer ### Étape 1: Créer le network Traefik (si pas déjà fait) ```bash docker network create traefik_network ``` ### Étape 2: Préparer les variables d'environnement #### Pour Staging: 1. Copier `.env.staging.example` vers `.env.staging` 2. Remplir toutes les valeurs (voir section Variables d'environnement ci-dessous) 3. **IMPORTANT**: Utiliser des mots de passe forts (min 32 caractères) #### Pour Production: 1. Copier `.env.production.example` vers `.env.production` 2. Remplir toutes les valeurs avec les credentials de production 3. **IMPORTANT**: Utiliser des mots de passe ultra-forts (min 64 caractères) ### Étape 3: Déployer via Portainer UI #### A. Accéder à Portainer - URL: `https://portainer.votre-domaine.com` (ou `http://IP:9000`) - Login avec vos credentials admin #### B. Créer la Stack Staging 1. **Aller dans**: Stacks → Add Stack 2. **Name**: `xpeditis-staging` 3. **Build method**: Web editor 4. **Copier le contenu** de `portainer-stack-staging.yml` 5. **Onglet "Environment variables"**: - Cliquer sur "Load variables from .env file" - Copier-coller le contenu de `.env.staging` - OU ajouter manuellement chaque variable 6. **Cliquer**: Deploy the stack 7. **Vérifier**: Les 4 services doivent démarrer (postgres, redis, backend, frontend) #### C. Créer la Stack Production 1. **Aller dans**: Stacks → Add Stack 2. **Name**: `xpeditis-production` 3. **Build method**: Web editor 4. **Copier le contenu** de `portainer-stack-production.yml` 5. **Onglet "Environment variables"**: - Cliquer sur "Load variables from .env file" - Copier-coller le contenu de `.env.production` - OU ajouter manuellement chaque variable 6. **Cliquer**: Deploy the stack 7. **Vérifier**: Les 6 services doivent démarrer (postgres, redis, backend x2, frontend x2) --- ## 🔐 Variables d'environnement Critiques ### Variables Obligatoires (staging & production) | Variable | Description | Exemple | |----------|-------------|---------| | `POSTGRES_PASSWORD` | Mot de passe PostgreSQL | `XpEd1t1s_pG_S3cur3_2024!` | | `REDIS_PASSWORD` | Mot de passe Redis | `R3d1s_C4ch3_P4ssw0rd!` | | `JWT_SECRET` | Secret pour JWT tokens | `openssl rand -base64 64` | | `AWS_ACCESS_KEY_ID` | AWS Access Key | `AKIAIOSFODNN7EXAMPLE` | | `AWS_SECRET_ACCESS_KEY` | AWS Secret Key | `wJalrXUtnFEMI/K7MDENG/...` | | `SENTRY_DSN` | Sentry monitoring URL | `https://xxx@sentry.io/123` | | `MAERSK_API_KEY` | Clé API Maersk | Voir portail Maersk | ### Générer des Secrets Sécurisés ```bash # PostgreSQL password (64 chars) openssl rand -base64 48 # Redis password (64 chars) openssl rand -base64 48 # JWT Secret (512 bits) openssl rand -base64 64 # Generic secure password pwgen -s 64 1 ``` --- ## 🔍 Vérification du Déploiement ### 1. Vérifier l'état des conteneurs Dans Portainer: - **Stacks** → `xpeditis-staging` (ou production) - Tous les services doivent être en status **running** (vert) ### 2. Vérifier les logs Cliquer sur chaque service → **Logs** → Vérifier qu'il n'y a pas d'erreurs ```bash # Ou via CLI docker logs xpeditis-backend-staging -f docker logs xpeditis-frontend-staging -f ``` ### 3. Vérifier les health checks ```bash # Backend health check curl https://api-staging.xpeditis.com/health # Réponse attendue: {"status":"ok","timestamp":"..."} # Frontend health check curl https://staging.xpeditis.com/api/health # Réponse attendue: {"status":"ok"} ``` ### 4. Vérifier Traefik Dans Traefik dashboard: - Routers: Doit afficher `xpeditis-backend-staging` et `xpeditis-frontend-staging` - Services: Doit afficher les load balancers avec health checks verts - Certificats: Let's Encrypt doit être vert ### 5. Vérifier SSL ```bash # Vérifier certificat SSL curl -I https://staging.xpeditis.com # Header "Strict-Transport-Security" doit être présent # Test SSL avec SSLLabs # https://www.ssllabs.com/ssltest/analyze.html?d=staging.xpeditis.com ``` ### 6. Test Complet 1. **Frontend**: Ouvrir `https://staging.xpeditis.com` dans un navigateur 2. **Backend**: Tester un endpoint: `https://api-staging.xpeditis.com/health` 3. **Login**: Créer un compte et se connecter 4. **Recherche de taux**: Tester une recherche Rotterdam → Shanghai 5. **Booking**: Créer un booking de test --- ## 🐛 Dépannage ### Problème 1: Service ne démarre pas **Symptôme**: Conteneur en status "Exited" ou "Restarting" **Solution**: 1. Vérifier les logs: Portainer → Service → Logs 2. Erreurs communes: - `POSTGRES_PASSWORD` manquant → Ajouter la variable - `Cannot connect to postgres` → Vérifier que postgres est en running - `Redis connection refused` → Vérifier que redis est en running - `Port already in use` → Un autre service utilise le port ### Problème 2: Traefik ne route pas vers le service **Symptôme**: 404 Not Found ou Gateway Timeout **Solution**: 1. Vérifier que le network `traefik_network` existe: ```bash docker network ls | grep traefik ``` 2. Vérifier que les services sont connectés au network: ```bash docker inspect xpeditis-backend-staging | grep traefik_network ``` 3. Vérifier les labels Traefik dans Portainer → Service → Labels 4. Restart Traefik: ```bash docker restart traefik ``` ### Problème 3: SSL Certificate Failed **Symptôme**: "Your connection is not private" ou certificat invalide **Solution**: 1. Vérifier que DNS pointe vers le serveur: ```bash nslookup staging.xpeditis.com ``` 2. Vérifier les logs Traefik: ```bash docker logs traefik | grep -i letsencrypt ``` 3. Vérifier que ports 80 et 443 sont ouverts: ```bash sudo ufw status sudo netstat -tlnp | grep -E '80|443' ``` 4. Si nécessaire, supprimer le certificat et re-déployer: ```bash docker exec traefik rm /letsencrypt/acme.json docker restart traefik ``` ### Problème 4: Database connection failed **Symptôme**: Backend logs montrent "Cannot connect to database" **Solution**: 1. Vérifier que PostgreSQL est en running 2. Vérifier les credentials: ```bash docker exec -it xpeditis-postgres-staging psql -U xpeditis -d xpeditis_staging ``` 3. Vérifier le network interne: ```bash docker exec -it xpeditis-backend-staging ping postgres-staging ``` ### Problème 5: High memory usage **Symptôme**: Serveur lent, OOM killer **Solution**: 1. Vérifier l'utilisation mémoire: ```bash docker stats ``` 2. Réduire les limites dans docker-compose (section `deploy.resources`) 3. Augmenter la RAM du serveur 4. Optimiser les queries PostgreSQL (indexes, explain analyze) --- ## 🔄 Mise à Jour des Stacks ### Update Rolling (Zero Downtime) #### Staging: 1. Build et push nouvelle image: ```bash docker build -t xpeditis/backend:staging-v1.2.0 . docker push xpeditis/backend:staging-v1.2.0 ``` 2. Dans Portainer → Stacks → `xpeditis-staging` → Editor 3. Changer `BACKEND_TAG=staging-v1.2.0` 4. Cliquer "Update the stack" 5. Portainer va pull la nouvelle image et redémarrer les services #### Production (avec High Availability): La stack production a 2 instances de chaque service (backend-prod-1, backend-prod-2). Traefik va load balancer entre les deux. **Mise à jour sans downtime**: 1. Stopper `backend-prod-2` dans Portainer 2. Update l'image de `backend-prod-2` 3. Redémarrer `backend-prod-2` 4. Vérifier health check OK 5. Stopper `backend-prod-1` 6. Update l'image de `backend-prod-1` 7. Redémarrer `backend-prod-1` 8. Vérifier health check OK **OU via Portainer** (plus simple): 1. Portainer → Stacks → `xpeditis-production` → Editor 2. Changer `BACKEND_TAG=v1.2.0` 3. Cliquer "Update the stack" 4. Portainer va mettre à jour les services un par un (rolling update automatique) --- ## 📊 Monitoring ### 1. Portainer Built-in Monitoring Portainer → Containers → Sélectionner service → **Stats** - CPU usage - Memory usage - Network I/O - Block I/O ### 2. Sentry (Error Tracking) Toutes les erreurs backend et frontend sont envoyées à Sentry (configuré via `SENTRY_DSN`) URL: https://sentry.io/organizations/xpeditis/projects/ ### 3. Logs Centralisés **Voir tous les logs en temps réel**: ```bash docker logs -f xpeditis-backend-staging docker logs -f xpeditis-frontend-staging docker logs -f xpeditis-postgres-staging docker logs -f xpeditis-redis-staging ``` **Rechercher dans les logs**: ```bash docker logs xpeditis-backend-staging 2>&1 | grep "ERROR" docker logs xpeditis-backend-staging 2>&1 | grep "booking" ``` ### 4. Health Checks Dashboard Créer un dashboard custom avec: - Uptime Robot: https://uptimerobot.com (free tier: 50 monitors) - Grafana + Prometheus (advanced) --- ## 🔒 Sécurité Best Practices ### 1. Mots de passe forts ✅ Min 64 caractères pour production ✅ Générés aléatoirement (openssl, pwgen) ✅ Stockés dans un gestionnaire de secrets (AWS Secrets Manager, Vault) ### 2. Rotation des credentials ✅ Tous les 90 jours ✅ Immédiatement si compromis ### 3. Backups automatiques ✅ PostgreSQL: Backup quotidien ✅ Retention: 30 jours staging, 90 jours production ✅ Test restore mensuel ### 4. Monitoring actif ✅ Sentry configuré ✅ Uptime monitoring actif ✅ Alertes email/Slack pour downtime ### 5. SSL/TLS ✅ HSTS activé (Strict-Transport-Security) ✅ TLS 1.2+ minimum ✅ Certificat Let's Encrypt auto-renew ### 6. Rate Limiting ✅ Traefik rate limiting configuré ✅ Application-level rate limiting (NestJS throttler) ✅ Brute-force protection active ### 7. Firewall ✅ Ports 80, 443 ouverts uniquement ✅ PostgreSQL/Redis accessibles uniquement depuis réseau interne Docker ✅ SSH avec clés uniquement (pas de mot de passe) --- ## 📞 Support ### En cas de problème critique: 1. **Vérifier les logs** dans Portainer 2. **Vérifier Sentry** pour les erreurs récentes 3. **Restart du service** via Portainer (si safe) 4. **Rollback**: Portainer → Stacks → Redeploy previous version ### Contacts: - **Tech Lead**: david-henri.arnaud@3ds.com - **DevOps**: ops@xpeditis.com - **Support**: support@xpeditis.com --- ## 📚 Ressources - **Portainer Docs**: https://docs.portainer.io/ - **Traefik Docs**: https://doc.traefik.io/traefik/ - **Docker Docs**: https://docs.docker.com/ - **Let's Encrypt**: https://letsencrypt.org/docs/ --- *Dernière mise à jour*: 2025-10-14 *Version*: 1.0.0 *Auteur*: Xpeditis DevOps Team