# Docker Compose for spotlight.cam # Usage: # Development: docker compose --profile dev up # Production: docker compose --profile prod up # Both: docker compose --profile dev --profile prod up services: # ============================================ # Nginx - Reverse Proxy & Static File Server # ============================================ nginx: image: nginx:alpine container_name: slc-proxy-dev depends_on: - frontend - backend volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d:/etc/nginx/conf.d:ro restart: unless-stopped profiles: ["dev"] ports: - "8080:80" networks: - slc_network nginx-prod: image: nginx:alpine container_name: slc-proxy-prod depends_on: - frontend-prod - backend-prod volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/conf.d.prod:/etc/nginx/conf.d:ro - ./ssl:/etc/nginx/ssl:ro - app_logs_prod:/var/log/nginx-app ports: - "80:80" - "443:443" restart: always command: ["/bin/sh", "-c", "nginx -g 'daemon off;' 2>&1 | tee -a /var/log/nginx-app/nginx.log"] logging: driver: "json-file" options: max-size: "50m" max-file: "10" deploy: resources: limits: cpus: '0.5' memory: 512M reservations: cpus: '0.25' memory: 256M profiles: ["prod"] networks: - slc_network # ============================================ # Frontend - React/Vite Application # ============================================ frontend: build: context: ./frontend dockerfile: Dockerfile container_name: slc-frontend-dev expose: - "5173" volumes: - ./frontend:/app - /app/node_modules env_file: - ./frontend/.env.development environment: - NODE_ENV=development - VITE_HOST=0.0.0.0 stdin_open: true tty: true command: npm run dev restart: unless-stopped profiles: ["dev"] networks: - slc_network frontend-prod: build: context: ./frontend dockerfile: Dockerfile.prod args: - NODE_ENV=production container_name: slc-frontend-prod expose: - "5173" environment: - NODE_ENV=production command: ["nginx", "-g", "daemon off;"] restart: always logging: driver: "json-file" options: max-size: "10m" max-file: "3" deploy: resources: limits: cpus: '0.5' memory: 512M reservations: cpus: '0.25' memory: 256M profiles: ["prod"] networks: - slc_network # ============================================ # Backend - Node.js/Express API # ============================================ backend: build: context: ./backend dockerfile: Dockerfile container_name: slc-backend-dev env_file: - ./backend/.env.development expose: - "3000" volumes: - ./backend:/app - /app/node_modules environment: - NODE_ENV=development - PORT=3000 # Scheduler (enable for a single backend instance) - ENABLE_SCHEDULER=true - SCHEDULER_INTERVAL_SEC=300 - MATCHING_MIN_INTERVAL_SEC=60 # Security: Relaxed for development - RATE_LIMIT_ENABLED=false - RATE_LIMIT_AUTH_MAX=100 - RATE_LIMIT_EMAIL_MAX=20 - ENABLE_CSRF=false - BODY_SIZE_LIMIT=50mb - LOG_LEVEL=debug depends_on: - db command: npm run dev restart: unless-stopped profiles: ["dev"] networks: - slc_network backend-prod: build: context: ./backend dockerfile: Dockerfile.prod args: - NODE_ENV=production container_name: slc-backend-prod env_file: - ./backend/.env.production expose: - "3000" environment: - NODE_ENV=production - PORT=3000 # Scheduler (enable on exactly one replica) - ENABLE_SCHEDULER=false - SCHEDULER_INTERVAL_SEC=300 - MATCHING_MIN_INTERVAL_SEC=120 # Security: Strict for production (override with .env file) - RATE_LIMIT_ENABLED=true - RATE_LIMIT_AUTH_MAX=5 - RATE_LIMIT_EMAIL_MAX=3 - ENABLE_CSRF=true - BODY_SIZE_LIMIT=10kb - LOG_LEVEL=warn depends_on: - db-prod command: ["sh", "-c", "node src/server.js 2>&1 | tee -a /var/log/app/backend.log"] restart: always volumes: - app_logs_prod:/var/log/app logging: driver: "json-file" options: max-size: "50m" max-file: "10" deploy: resources: limits: cpus: '1.5' memory: 2G reservations: cpus: '1.0' memory: 1G profiles: ["prod"] networks: - slc_network # ============================================ # Database - PostgreSQL # ============================================ db: image: postgres:15-alpine container_name: slc-db-dev environment: - POSTGRES_USER=spotlightcam - POSTGRES_PASSWORD=spotlightcam123 - POSTGRES_DB=spotlightcam volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" # Exposed for dev tools restart: unless-stopped profiles: ["dev"] networks: - slc_network db-prod: image: postgres:15-alpine container_name: slc-db-prod environment: - POSTGRES_USER=${POSTGRES_USER:-spotlightcam} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-spotlightcam123} - POSTGRES_DB=${POSTGRES_DB:-spotlightcam} volumes: - postgres_data_prod:/var/lib/postgresql/data - ./backups:/backups # No exposed ports in production (internal only) restart: always logging: driver: "json-file" options: max-size: "10m" max-file: "3" deploy: resources: limits: cpus: '1.0' memory: 3G reservations: cpus: '0.75' memory: 2G profiles: ["prod"] networks: - slc_network volumes: postgres_data: driver: local postgres_data_prod: external: true name: slc_postgres_prod_data app_logs_prod: external: true name: slc_logs_prod networks: slc_network: driver: bridge name: slc_network