Some checks are pending
CD Production (Hetzner k3s) / Promote Images (preprod → prod) (push) Waiting to run
CD Production (Hetzner k3s) / Deploy to k3s (xpeditis-prod) (push) Blocked by required conditions
CD Production (Hetzner k3s) / Smoke Tests (push) Blocked by required conditions
CD Production (Hetzner k3s) / Deployment Summary (push) Blocked by required conditions
CD Production (Hetzner k3s) / Notify Success (push) Blocked by required conditions
CD Production (Hetzner k3s) / Notify Failure (push) Blocked by required conditions
Aligns main with the complete application codebase (cicd branch). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
420 lines
11 KiB
Markdown
420 lines
11 KiB
Markdown
# 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
|