# 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`](../../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é `postgres` ou `api` collisionne. Tout est préfixé, sans exception. - Seul `siop2-web` rejoint `dokploy-network` (réseau externe du reverse-proxy) : l'API n'est **jamais** exposée directement, elle est servie via le proxy `/api` de 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-accounts` et `/auth/demo-login` n'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) 1. Dokploy → **Create Project** `siop2` → **Compose** ; source = dépôt `siop-spelev/siop2`, branche `main`, fichier `infra/docker-compose.dokploy.yml`. 2. Renseigner les variables d'environnement (§2) dans l'onglet Environment. 3. **Deploy**. Dokploy construit les images (contexte = racine du dépôt, Dockerfiles `apps/api` et `apps/web`) puis démarre les 5 services ; l'API attend PostgreSQL/Redis/MinIO sains (healthchecks) et migre la base. 4. Onglet Domains du service `siop2-web` : associer le domaine (port **80**, HTTPS Let's Encrypt géré par Dokploy). 5. Vérifications : - `https:///api/health` → `{"status":"ok", ...}` (les 3 services `up`) ; - production client : `https:///api/auth/demo-accounts` → **404** ; - instance démo : écran de connexion avec les 7 comptes, bascule de rôle < 3 s. 6. 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 `DROP` sans 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=true` sans `DEMO_MODE_I_KNOW` (verrou ADR-002 — c'est voulu), `DATABASE_URL` erronée, migration échouée. - **Sauvegardes** : volumes `pg-data` (base) et `minio-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) ```bash # 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.