version: '3.8' services: # --------------------------------------------------------------- # Backend - FastAPI (Production) # --------------------------------------------------------------- backend: build: context: ./backend dockerfile: Dockerfile target: production container_name: insight-updater-backend restart: unless-stopped environment: - APP_ENV=production - DATABASE_URL=postgresql+asyncpg://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME} - REDIS_URL=redis://redis:6379/0 - SECRET_KEY=${SECRET_KEY} - ENCRYPTION_KEY=${ENCRYPTION_KEY} - JWT_PRIVATE_KEY_PATH=/app/keys/private.pem - JWT_PUBLIC_KEY_PATH=/app/keys/public.pem - WINRM_TRANSPORT=${WINRM_TRANSPORT:-ntlm} - WINRM_CERT_VALIDATION=${WINRM_CERT_VALIDATION:-validate} - LDAP_ENABLED=${LDAP_ENABLED:-false} - LDAP_URI=${LDAP_URI} - LDAP_BIND_DN=${LDAP_BIND_DN} - LDAP_BIND_PASSWORD=${LDAP_BIND_PASSWORD} - LDAP_USER_SEARCH_BASE=${LDAP_USER_SEARCH_BASE} - LDAP_USER_FILTER=${LDAP_USER_FILTER} - LOG_LEVEL=${LOG_LEVEL:-INFO} - LOG_FORMAT=json volumes: - ./data:/app/data - ./keys:/app/keys:ro - ./certs:/app/certs:ro networks: - internal - traefik-public deploy: resources: limits: cpus: '1.0' memory: 1G reservations: cpus: '0.25' memory: 256M healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 start_period: 20s labels: - "traefik.enable=true" - "traefik.docker.network=traefik-public" - "traefik.http.routers.updater-api.rule=Host(`${DOMAIN}`) && PathPrefix(`/api`)" - "traefik.http.routers.updater-api.entrypoints=websecure" - "traefik.http.routers.updater-api.tls.certresolver=letsencrypt" - "traefik.http.services.updater-api.loadbalancer.server.port=8000" - "traefik.http.routers.updater-ws.rule=Host(`${DOMAIN}`) && PathPrefix(`/ws`)" - "traefik.http.routers.updater-ws.entrypoints=websecure" - "traefik.http.routers.updater-ws.tls.certresolver=letsencrypt" - "traefik.http.services.updater-ws.loadbalancer.server.port=8000" # --------------------------------------------------------------- # Frontend - Nginx (Production) # --------------------------------------------------------------- frontend: build: context: ./frontend dockerfile: Dockerfile target: production container_name: insight-updater-frontend restart: unless-stopped networks: - internal - traefik-public labels: - "traefik.enable=true" - "traefik.docker.network=traefik-public" - "traefik.http.routers.updater-web.rule=Host(`${DOMAIN}`)" - "traefik.http.routers.updater-web.entrypoints=websecure" - "traefik.http.routers.updater-web.tls.certresolver=letsencrypt" - "traefik.http.services.updater-web.loadbalancer.server.port=80" # --------------------------------------------------------------- # Redis - Pub/Sub, Caching, Rate Limiting # --------------------------------------------------------------- redis: image: redis:7-alpine container_name: insight-updater-redis restart: unless-stopped command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru volumes: - redis-data:/data networks: - internal healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 3s retries: 3 # --------------------------------------------------------------- # PostgreSQL - Production Database # --------------------------------------------------------------- db: image: postgres:16-alpine container_name: insight-updater-db restart: unless-stopped environment: - POSTGRES_DB=${DB_NAME} - POSTGRES_USER=${DB_USER} - POSTGRES_PASSWORD=${DB_PASSWORD} volumes: - pg-data:/var/lib/postgresql/data networks: - internal healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"] interval: 10s timeout: 3s retries: 3 deploy: resources: limits: cpus: '0.5' memory: 512M networks: internal: driver: bridge traefik-public: external: true volumes: redis-data: pg-data: