# SIOP V2 — compose de PRODUCTION (Dokploy). Voir docs/06-production/runbook-dokploy.md. # CONVENTION (leçon v1) : tout service/conteneur est préfixé « siop2- » — le # réseau Dokploy est partagé entre projets, un nom générique collisionne. # Les secrets (${...}) vivent dans l'environnement du projet Dokploy, jamais ici. name: siop2 services: siop2-postgres: container_name: siop2-postgres build: ./postgres image: siop2/postgres:18-pgvector-postgis restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER:-siop} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?définir POSTGRES_PASSWORD dans Dokploy} POSTGRES_DB: ${POSTGRES_DB:-siop} volumes: - pg-data:/var/lib/postgresql - ./postgres/init.sql:/docker-entrypoint-initdb.d/10-extensions.sql:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-siop} -d ${POSTGRES_DB:-siop}"] interval: 5s timeout: 3s retries: 10 siop2-redis: container_name: siop2-redis image: redis:7.4.9-alpine restart: unless-stopped volumes: - redis-data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 10 siop2-minio: container_name: siop2-minio image: minio/minio:RELEASE.2025-09-07T16-13-09Z restart: unless-stopped command: server /data --console-address ":9001" environment: MINIO_ROOT_USER: ${MINIO_ROOT_USER:-siop} MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?définir MINIO_ROOT_PASSWORD dans Dokploy} volumes: - minio-data:/data healthcheck: test: ["CMD", "mc", "ready", "local"] interval: 5s timeout: 3s retries: 10 # Service IA (R5, ADR-004) : JAMAIS sur dokploy-network — seul siop2-api le # contacte, avec le secret partagé AI_SERVICE_TOKEN. Le modèle d'embeddings # est dans l'image (pas de téléchargement au boot). Sans AI_API_KEY, le # service tourne en mode extractif — pleinement fonctionnel (recette R5). siop2-ai: container_name: siop2-ai build: context: ../apps/ai dockerfile: Dockerfile image: siop2/ai:latest restart: unless-stopped environment: DATABASE_URL: postgresql://${POSTGRES_USER:-siop}:${POSTGRES_PASSWORD}@siop2-postgres:5432/${POSTGRES_DB:-siop} MINIO_ENDPOINT: siop2-minio MINIO_PORT: 9000 MINIO_ACCESS_KEY: ${MINIO_ROOT_USER:-siop} MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD} AI_SERVICE_TOKEN: ${AI_SERVICE_TOKEN:?définir AI_SERVICE_TOKEN dans Dokploy} # Génération opt-in (ADR-004 §3) : off par défaut ; pour l'activer, # AI_GENERATION=api + AI_API_KEY (secret Dokploy, jamais dans ce fichier). AI_GENERATION: ${AI_GENERATION:-off} AI_API_KEY: ${AI_API_KEY:-} AI_MODEL: ${AI_MODEL:-claude-opus-4-8} # Seuils de similarité — à calibrer sur le corpus client (runbook §7) AI_SEUIL_PERTINENCE: ${AI_SEUIL_PERTINENCE:-0.45} AI_SEUIL_SUGGESTION: ${AI_SEUIL_SUGGESTION:-0.40} AI_SEUIL_CONFIANCE_FORTE: ${AI_SEUIL_CONFIANCE_FORTE:-0.55} depends_on: siop2-postgres: condition: service_healthy siop2-minio: condition: service_healthy siop2-api: container_name: siop2-api build: context: .. dockerfile: apps/api/Dockerfile image: siop2/api:latest restart: unless-stopped environment: NODE_ENV: production PORT: 3000 DATABASE_URL: postgresql://${POSTGRES_USER:-siop}:${POSTGRES_PASSWORD}@siop2-postgres:5432/${POSTGRES_DB:-siop} REDIS_URL: redis://siop2-redis:6379 JWT_SECRET: ${JWT_SECRET:?définir JWT_SECRET dans Dokploy} MINIO_ENDPOINT: siop2-minio MINIO_PORT: 9000 MINIO_ACCESS_KEY: ${MINIO_ROOT_USER:-siop} MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD} # R5 : l'assistant passe par le service interne (503 propre s'il dort) AI_SERVICE_URL: http://siop2-ai:8000 AI_SERVICE_TOKEN: ${AI_SERVICE_TOKEN} # ADR-002 — production client : les 3 variables restent ABSENTES. # Instance de démonstration publique UNIQUEMENT : # DEMO_MODE=true + DEMO_MODE_I_KNOW=true (double verrou) + SEED_ON_START=true DEMO_MODE: ${DEMO_MODE:-} DEMO_MODE_I_KNOW: ${DEMO_MODE_I_KNOW:-} SEED_ON_START: ${SEED_ON_START:-} SEED_DEMO_PASSWORD: ${SEED_DEMO_PASSWORD:-} depends_on: siop2-postgres: condition: service_healthy siop2-redis: condition: service_healthy siop2-minio: condition: service_healthy siop2-web: container_name: siop2-web build: context: .. dockerfile: apps/web/Dockerfile image: siop2/web:latest restart: unless-stopped environment: API_UPSTREAM: siop2-api:3000 depends_on: - siop2-api networks: - default - dokploy-network volumes: pg-data: redis-data: minio-data: networks: # Réseau du reverse-proxy Dokploy (Traefik) : seul siop2-web y est exposé, # le domaine pointe sur lui (port 80) ; l'API reste interne (proxy /api). dokploy-network: external: true