- image api : multi-stage (pnpm deploy --legacy --prod), client Prisma régénéré dans l'arborescence déployée, binaryTargets explicites (debian/arm64 openssl-3), entrypoint migrate deploy → seed optionnel (SEED_ON_START, compilé dist/seed) → API ; non-root, healthcheck /health - image web : nginx alpine, statique Vite, proxy /api résolu À LA REQUÊTE (resolver Docker + variable — nginx démarre sans l'API), fallback SPA, cache immuable /assets, healthcheck IPv4 (127.0.0.1) - infra/docker-compose.dokploy.yml : 5 services préfixés siop2-, secrets exigés, seul siop2-web rejoint dokploy-network (API jamais exposée) - runbook docs/06-production/runbook-dokploy.md : topologie, profils d'environnement, checklist première prod, rollback, répétition locale - répétition locale validée de bout en bout : migrate+seed au boot, parcours demo-login → /users/me à travers nginx conteneurisé, conteneurs healthy ; le double verrou ADR-002 (DEMO_MODE sans I_KNOW en production) a refusé de démarrer — observé en situation réelle - prisma passe en dépendance de production (migrations au boot) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5.4 KiB
Runbook — déploiement Dokploy
Rôle de ce document (playbook) : la procédure REJOUABLE de mise en production sur Dokploy (PaaS auto-hébergé du partenaire), écrite en R0.13 et répétée à chaque release (principe « déployer tôt »). Statut : répété en local, en attente des accès au serveur du partenaire pour la première exécution réelle.
1. Topologie
Un projet Dokploy = un service « Compose » pointant sur ce dépôt,
fichier infra/docker-compose.dokploy.yml :
domaine (Traefik/Dokploy) ──▶ siop2-web :80 (nginx, statique)
│ /api/** (préfixe retiré)
▼
siop2-api :3000 (NestJS)
│── siop2-postgres :5432 (pgvector + PostGIS)
│── siop2-redis :6379
└── siop2-minio :9000
- Convention
siop2-(leçon v1) : le réseau Dokploy est partagé entre projets ; un service nommépostgresouapicollisionne. Tout est préfixé, sans exception. - Seul
siop2-webrejointdokploy-network(réseau externe du reverse-proxy) : l'API n'est jamais exposée directement, elle est servie via le proxy/apide nginx — même topologie que le proxy Vite en dev, donc mêmes chemins partout. - Les migrations Prisma s'appliquent au démarrage du conteneur API
(
prisma migrate deploy, idempotent) : la base est toujours au niveau du code déployé.
2. Variables d'environnement (à saisir dans Dokploy, jamais dans le dépôt)
| Variable | Obligatoire | Rôle |
|---|---|---|
POSTGRES_PASSWORD |
✅ | mot de passe PostgreSQL (générer : openssl rand -hex 24) |
MINIO_ROOT_PASSWORD |
✅ | secret MinIO |
JWT_SECRET |
✅ | signature des jetons (générer : openssl rand -hex 32) |
POSTGRES_USER / POSTGRES_DB |
— | défaut siop / siop |
DEMO_MODE |
— | absent en production client. true uniquement sur l'instance de démonstration |
DEMO_MODE_I_KNOW |
— | double verrou ADR-002 : requis si DEMO_MODE=true en production, sinon l'API refuse de démarrer |
SEED_ON_START |
— | true sur l'instance de démonstration : rôles, matrice et comptes démo au boot (idempotent) |
SEED_DEMO_PASSWORD |
— | mot de passe commun des comptes démo (défaut Demo!2026) |
Profils types :
- Production client : les 4 dernières variables absentes. Les routes
/auth/demo-accountset/auth/demo-loginn'existent pas (404, testé en CI). - Instance de démonstration :
DEMO_MODE=true,DEMO_MODE_I_KNOW=true,SEED_ON_START=true.
3. Première mise en production (checklist)
- Dokploy → Create Project
siop2→ Compose ; source = dépôtsiop-spelev/siop2, branchemain, fichierinfra/docker-compose.dokploy.yml. - Renseigner les variables d'environnement (§2) dans l'onglet Environment.
- Deploy. Dokploy construit les images (contexte = racine du dépôt,
Dockerfiles
apps/apietapps/web) puis démarre les 5 services ; l'API attend PostgreSQL/Redis/MinIO sains (healthchecks) et migre la base. - Onglet Domains du service
siop2-web: associer le domaine (port 80, HTTPS Let's Encrypt géré par Dokploy). - Vérifications :
https://<domaine>/api/health→{"status":"ok", ...}(les 3 servicesup) ;- production client :
https://<domaine>/api/auth/demo-accounts→ 404 ; - instance démo : écran de connexion avec les 7 comptes, bascule de rôle < 3 s.
- Consigner la mise en production dans
docs/journal/journal.md(date, version, domaine).
4. Releases suivantes
git push sur main (CI verte exigée) → Dokploy Deploy (ou webhook auto-deploy).
Les migrations de la release s'appliquent au démarrage ; en cas d'échec de migration,
le conteneur s'arrête sans servir de trafic (l'ancienne version reste visible côté web).
5. Incidents & retours arrière
- Rollback applicatif : Dokploy → Deployments → redéployer le commit précédent.
Les migrations Prisma étant additives (convention projet : jamais de
DROPsans tâche dédiée validée), l'ancienne API fonctionne sur le schéma plus récent. - API en échec au boot :
docker logs siop2-api. Causes classiques :DEMO_MODE=truesansDEMO_MODE_I_KNOW(verrou ADR-002 — c'est voulu),DATABASE_URLerronée, migration échouée. - Sauvegardes : volumes
pg-data(base) etminio-data(fichiers). Sauvegarde PostgreSQL planifiée côté Dokploy (onglet Backups) — à configurer à la première mise en production réelle.
6. Répétition locale (sans Dokploy)
# depuis la racine — construit et lance les 5 services comme en production
docker network create dokploy-network 2>/dev/null || true
POSTGRES_PASSWORD=repetition MINIO_ROOT_PASSWORD=repetition-minio \
JWT_SECRET=$(openssl rand -hex 32) DEMO_MODE=true DEMO_MODE_I_KNOW=true SEED_ON_START=true \
docker compose -f infra/docker-compose.dokploy.yml up -d --build
# web : http://localhost via un port publié à ajouter ponctuellement, ou :
docker compose -f infra/docker-compose.dokploy.yml exec siop2-web wget -qO- http://localhost/api/health
C'est cette répétition (images construites, migrations au boot, parcours démo via nginx) qui a validé R0.13 en local — voir le journal du 15/07/2026.