Date : 10/02/2026
Status : A VALIDER
Scope : smart-deploy (strategies/docker.sh, lib/nginx.sh), nginx VM
La strategie zero-downtime dans docker.sh n'est pas du vrai zero-downtime :
1. Start staging (port+10000)
2. Health check staging ← OK jusque la
3. STOP staging ← les 2 sont down
4. STOP production ← les 2 sont down
5. Start nouveau sur port prod ← downtime ~3-5s
Il y a un trou entre l'etape 3 et 5 ou RIEN ne repond. C'est un "validated restart", pas du blue-green.
AVANT APRES
┌─────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐
│ nginx │───►│ BLUE │ │ nginx │───►│ GREEN │
│ │ │ port 5501│ │ │ │ port 5511│
└─────────┘ └──────────┘ └─────────┘ └──────────┘
┌──────────┐
│ BLUE │ ← drain + stop
│ port 5501│
└──────────┘
Nginx fait le switch atomiquement. L'ancien container continue de servir les requetes en cours pendant le switch. Zero requete perdue.
1. Identifier le slot actif (BLUE=port, GREEN=port+10)
- Lire /etc/nginx/sites-available/<domain>.conf
- Trouver le port actif dans proxy_pass
- L'autre slot = le nouveau
2. Build & Push image (inchange)
3. Start GREEN container (port inactif)
- docker compose up -d avec le port GREEN
- Container name: <name>-green ou <name>-blue selon le slot
4. Health check GREEN (nos nouvelles etapes 9a/9b/9c)
- 9a: Container running
- 9b: Port GREEN ready
- 9c: HTTP /health sur port GREEN
5. Nginx switch (ATOMIQUE)
- Modifier proxy_pass dans la config nginx
- nginx -t (test config)
- nginx -s reload (zero-downtime reload natif nginx)
6. Health check via HTTPS (etape 9d)
- Verifier que le domaine pointe maintenant vers GREEN
7. Drain & Stop BLUE (ancien)
- Attendre 10s (drain des connexions en cours)
- docker stop <name>-blue
- docker rm <name>-blue
8. Cleanup
- Prune images anciennes
strategies/docker.sh - Nouvelle strategie blue-greencase "$strategy" in
blue-green|bg)
deploy_blue_green "$latest_image"
;;
zero-downtime|zdt)
# ... existant
;;
simple|*)
# ... existant
;;
esac
Fonction deploy_blue_green() qui :
nginx_switch_upstream pour basculerlib/nginx.sh - Fonctions de switch# Lire le port actif dans la conf nginx
nginx_get_active_port() {
local domain="$1"
ssh nginx "grep proxy_pass /etc/nginx/sites-available/${domain}.conf | grep -oP ':\K[0-9]+'"
}
# Switch le proxy_pass vers un nouveau port
nginx_switch_upstream() {
local domain="$1"
local new_port="$2"
ssh nginx "sudo sed -i 's/proxy_pass http:\/\/[0-9.]*:[0-9]*/proxy_pass http:\/\/192.168.1.12:${new_port}/' /etc/nginx/sites-available/${domain}.conf"
ssh nginx "sudo nginx -t && sudo nginx -s reload"
}
Note : Ceci modifie nginx en SSH direct. C'est une exception justifiee car le switch doit etre atomique et rapide. La conf de base est toujours generee par smart-deploy lors du premier deploiement. Le blue-green ne modifie QUE le port dans proxy_pass.
conf.prod.gouroubleu.yml - Configurationname: "mon-api"
deploy_strategy: "blue-green" # active le blue-green
port: 5501 # port BLUE
port_green: 5511 # port GREEN (defaut: port+10)
| Slot | Port | Container name |
|---|---|---|
| BLUE | port (ex: 5501) |
<name>-blue |
| GREEN | port + 10 (ex: 5511) |
<name>-green |
L'offset de 10 (au lieu de 10000) simplifie la gestion et evite les conflits avec d'autres services.
Deux options :
Option A : Lire la conf nginx (recommande)
nginx_get_active_port() retourne le port actifOption B : Fichier d'etat local
/monitoring/blue-green-state/<name>.json : {"active": "blue", "port": 5501}→ Option A : nginx EST la source de verite.
Le rollback blue-green est trivial et instantane :
# Re-switch nginx vers l'ancien slot (toujours running)
nginx_switch_upstream "$domain" "$old_port"
Pas besoin de pull d'image, pas de redemarrage container. L'ancien tourne encore pendant la phase de drain. C'est le rollback le plus rapide possible.
Premier deploiement (pas de container existant) :
Services avec sidecars (connectors-api + wireguard) :
network_mode: service:sidecar → le blue-green doit gerer les 2 containers ensembleServices sans domaine nginx :
simpleVolumes persistes :
| Aspect | Avant (simple) | Apres (blue-green) |
|---|---|---|
| Downtime | 3-5s | 0s |
| Rollback | Pull image + restart (~30s) | Nginx reload (~1s) |
| Ports utilises | 1 par service | 2 par service |
| Complexite | Faible | Moyenne |
| Requetes perdues | Oui (pendant stop/start) | Non |
| Service | Port | Candidat | Raison |
|---|---|---|---|
| connectors-api | 5403 | Non (v1) | network_mode sidecar, complexe |
| connectors-front | 5402 | Oui | Stateless, simple |
| ai-orchestrator | 5501 | Oui | Stateless, frequent deploys |
| browser-connector | 5404 | Oui | Stateless |
| notif-logger | 5300 | Oui | Stateless |
| qwikpress | 3002 | Oui | Stateless |
lib/nginx.sh : ajouter nginx_get_active_port() et nginx_switch_upstream()strategies/docker.sh : ajouter deploy_blue_green() avec detection slot, start green, health check, switch, drainsmart-deploy.sh : adapter les etapes 9a-9d pour supporter les deux slots (container name dynamique)deploy_strategy: "blue-green", verifier le switch