version: '3.8' services: # ============================================================================ # INFRASTRUCTURE SERVICES # ============================================================================ postgres: image: postgres:16-alpine container_name: veza_postgres restart: unless-stopped environment: POSTGRES_USER: ${DB_USER:-veza} POSTGRES_PASSWORD: ${DB_PASS:-password} POSTGRES_DB: ${DB_NAME:-veza} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-veza}"] interval: 5s timeout: 5s retries: 5 networks: - veza-network deploy: resources: limits: cpus: '0.50' memory: 256M redis: image: redis:7-alpine container_name: veza_redis restart: unless-stopped volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 networks: - veza-network deploy: resources: limits: cpus: '0.25' memory: 64M rabbitmq: image: rabbitmq:3-management-alpine container_name: veza_rabbitmq restart: unless-stopped environment: RABBITMQ_DEFAULT_USER: ${DB_USER:-veza} RABBITMQ_DEFAULT_PASS: ${DB_PASS:-password} volumes: - rabbitmq_data:/var/lib/rabbitmq healthcheck: test: rabbitmq-diagnostics -q ping interval: 10s timeout: 10s retries: 5 networks: - veza-network deploy: resources: limits: cpus: '0.50' memory: 256M # ============================================================================ # APPLICATION SERVICES # ============================================================================ backend-api: build: context: ./veza-backend-api dockerfile: Dockerfile.production image: veza-backend-api:latest container_name: veza_backend_api restart: unless-stopped environment: - APP_ENV=production - DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:-password}@postgres:5432/${DB_NAME:-veza}?sslmode=disable - REDIS_URL=redis://redis:6379 - AMQP_URL=amqp://${DB_USER:-veza}:${DB_PASS:-password}@rabbitmq:5672 - JWT_SECRET=${JWT_SECRET:-change-me-in-production-minimum-32-characters} - COOKIE_SECURE=true - COOKIE_SAME_SITE=strict - COOKIE_HTTP_ONLY=true - CORS_ALLOWED_ORIGINS=${CORS_ORIGINS:-http://veza.fr} depends_on: postgres: condition: service_healthy redis: condition: service_healthy rabbitmq: condition: service_healthy networks: - veza-network healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/api/v1/health"] interval: 10s timeout: 5s retries: 3 chat-server: build: context: ./veza-chat-server dockerfile: Dockerfile.production image: veza-chat-server:latest container_name: veza_chat_server restart: unless-stopped environment: - DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:-password}@postgres:5432/${DB_NAME:-veza}?sslmode=disable - REDIS_URL=redis://redis:6379 - JWT_SECRET=${JWT_SECRET:-change-me-in-production-minimum-32-characters} - PORT=3000 depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - veza-network healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"] interval: 10s timeout: 5s retries: 3 stream-server: build: context: ./veza-stream-server dockerfile: Dockerfile.production image: veza-stream-server:latest container_name: veza_stream_server restart: unless-stopped environment: - DATABASE_URL=postgres://${DB_USER:-veza}:${DB_PASS:-password}@postgres:5432/${DB_NAME:-veza}?sslmode=disable - REDIS_URL=redis://redis:6379 - PORT=3001 depends_on: postgres: condition: service_healthy redis: condition: service_healthy networks: - veza-network healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3001/health"] interval: 10s timeout: 5s retries: 3 web: build: context: ./apps/web dockerfile: Dockerfile.production image: veza-web:latest container_name: veza_web restart: unless-stopped environment: - VITE_API_URL=http://haproxy/api/v1 - VITE_WS_URL=ws://haproxy/ws - VITE_STREAM_URL=ws://haproxy/stream - VITE_UPLOAD_URL=http://haproxy/api/v1/uploads depends_on: - backend-api - chat-server - stream-server networks: - veza-network healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:5173"] interval: 10s timeout: 5s retries: 3 # ============================================================================ # REVERSE PROXY - HAProxy # ============================================================================ haproxy: image: haproxy:2.8-alpine container_name: veza_haproxy restart: unless-stopped ports: - "${PORT_HAPROXY:-80}:80" - "443:443" volumes: - ./config/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro depends_on: - backend-api - chat-server - stream-server - web networks: - veza-network healthcheck: test: ["CMD", "haproxy", "-c", "-f", "/usr/local/etc/haproxy/haproxy.cfg"] interval: 10s timeout: 5s retries: 3 networks: veza-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16 volumes: postgres_data: redis_data: rabbitmq_data: