services: # ============================================================================= # BACKEND API - PHP 8.5 + FrankenPHP # ============================================================================= php: build: context: ./backend dockerfile: Dockerfile target: dev container_name: classeo_php # FrankenPHP charge les variables d'environnement système AVANT que Symfony # ne parse le fichier .env. Sans env_file, les variables du .env ne seraient # pas disponibles au démarrage de FrankenPHP. # Avantage : une seule source de vérité (.env), pas de duplication. # Note : les variables dans 'environment:' ci-dessous écrasent celles du .env env_file: - ./backend/.env environment: # Overrides pour Docker : les hostnames des services utilisent les noms # des containers (db, redis, rabbitmq...) au lieu de localhost # APP_ENV peut être overridé en CI pour désactiver le rate limiting (test) APP_ENV: ${APP_ENV:-dev} DATABASE_URL: postgresql://classeo:classeo@db:5432/classeo_master?serverVersion=18&charset=utf8 REDIS_URL: redis://redis:6379 MESSENGER_TRANSPORT_DSN: amqp://guest:guest@rabbitmq:5672/%2f/messages MERCURE_URL: http://mercure/.well-known/mercure MEILISEARCH_URL: http://meilisearch:7700 MAILER_DSN: ${MAILER_DSN:-smtp://mailpit:1025} ports: - "18000:8000" # Port externe 18000 pour eviter conflit volumes: - ./backend:/app:cached - caddy_data:/data - caddy_config:/config depends_on: db: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/docs"] interval: 10s timeout: 5s retries: 5 start_period: 30s restart: unless-stopped # ============================================================================= # FRONTEND - SvelteKit + Node.js # ============================================================================= frontend: build: context: ./frontend dockerfile: Dockerfile target: dev container_name: classeo_frontend environment: # URL de fallback, sera remplacée dynamiquement par le hostname en multi-tenant PUBLIC_API_URL: http://localhost:18000/api PUBLIC_API_PORT: "18000" PUBLIC_BASE_DOMAIN: classeo.local PUBLIC_MERCURE_URL: http://localhost:3000/.well-known/mercure ports: - "5174:5173" # Port externe 5174 pour eviter conflit volumes: - ./frontend:/app:cached - frontend_node_modules:/app/node_modules healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:5173/"] interval: 10s timeout: 5s retries: 5 start_period: 30s restart: unless-stopped # ============================================================================= # DATABASE - PostgreSQL 18.1 # ============================================================================= db: image: postgres:18.1-alpine container_name: classeo_db environment: POSTGRES_DB: classeo_master POSTGRES_USER: classeo POSTGRES_PASSWORD: classeo ports: - "5433:5432" # Port externe 5433 pour eviter conflit avec PostgreSQL local volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U classeo -d classeo_master"] interval: 10s timeout: 5s retries: 5 start_period: 10s restart: unless-stopped # ============================================================================= # CACHE & SESSIONS - Redis 7.4 # ============================================================================= redis: image: redis:7.4-alpine container_name: classeo_redis command: redis-server --appendonly yes ports: - "6380:6379" # Port externe 6380 pour eviter conflit avec Redis local volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 5s restart: unless-stopped # ============================================================================= # MESSAGE QUEUE - RabbitMQ 4.2 # ============================================================================= rabbitmq: image: rabbitmq:4.2-management-alpine container_name: classeo_rabbitmq environment: RABBITMQ_DEFAULT_USER: guest RABBITMQ_DEFAULT_PASS: guest ports: - "5672:5672" - "15672:15672" volumes: - rabbitmq_data:/var/lib/rabbitmq healthcheck: test: ["CMD", "rabbitmq-diagnostics", "-q", "ping"] interval: 30s timeout: 10s retries: 5 start_period: 30s restart: unless-stopped # ============================================================================= # REAL-TIME SSE - Mercure # ============================================================================= mercure: image: dunglas/mercure:latest container_name: classeo_mercure environment: MERCURE_PUBLISHER_JWT_KEY: "mercure_publisher_secret_change_me_in_production" MERCURE_SUBSCRIBER_JWT_KEY: "mercure_subscriber_secret_change_me_in_production" SERVER_NAME: ":80" MERCURE_EXTRA_DIRECTIVES: | cors_origins http://localhost:5174 anonymous ports: - "3000:80" healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost/.well-known/mercure"] interval: 10s timeout: 5s retries: 5 start_period: 10s restart: unless-stopped # ============================================================================= # FULL-TEXT SEARCH - Meilisearch 1.12 # ============================================================================= meilisearch: image: getmeili/meilisearch:v1.12 container_name: classeo_meilisearch environment: MEILI_MASTER_KEY: "masterKey" MEILI_ENV: "development" ports: - "7700:7700" volumes: - meilisearch_data:/meili_data healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:7700/health"] interval: 10s timeout: 5s retries: 5 start_period: 10s restart: unless-stopped # ============================================================================= # EMAIL TESTING - Mailpit # ============================================================================= mailpit: image: axllent/mailpit:latest container_name: classeo_mailpit ports: - "1025:1025" - "8025:8025" healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:8025"] interval: 10s timeout: 5s retries: 5 start_period: 5s restart: unless-stopped # ============================================================================= # VOLUMES PERSISTANTS # ============================================================================= volumes: postgres_data: redis_data: rabbitmq_data: meilisearch_data: frontend_node_modules: caddy_data: caddy_config: