version: '3.8' services: # PostgreSQL Database postgres: image: postgres:15-alpine container_name: drone-detection-db restart: unless-stopped environment: POSTGRES_DB: drone_detection POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres123 PGDATA: /var/lib/postgresql/data/pgdata volumes: - postgres_data:/var/lib/postgresql/data - ./server/scripts/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql ports: - "5433:5432" networks: - drone-network healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d drone_detection"] interval: 30s timeout: 10s retries: 3 # Redis for session management and caching redis: image: redis:7-alpine container_name: drone-detection-redis restart: unless-stopped command: redis-server --appendonly yes volumes: - redis_data:/data ports: - "6380:6379" networks: - drone-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 10s retries: 3 # Backend API Server backend: build: context: ./server dockerfile: Dockerfile container_name: drone-detection-backend restart: unless-stopped environment: NODE_ENV: production PORT: 3001 DB_HOST: postgres DB_PORT: 5432 DB_NAME: drone_detection DB_USER: postgres DB_PASSWORD: postgres123 REDIS_HOST: redis REDIS_PORT: 6379 JWT_SECRET: ${JWT_SECRET:-your-super-secret-jwt-key-change-in-production} TWILIO_ACCOUNT_SID: ${TWILIO_ACCOUNT_SID:-} TWILIO_AUTH_TOKEN: ${TWILIO_AUTH_TOKEN:-} TWILIO_PHONE_NUMBER: ${TWILIO_PHONE_NUMBER:-} CORS_ORIGIN: http://localhost:3001 API_DEBUG: ${API_DEBUG:-false} STORE_HEARTBEATS: ${STORE_HEARTBEATS:-false} STORE_DRONE_TYPE0: ${STORE_DRONE_TYPE0:-false} LOG_ALL_DETECTIONS: ${LOG_ALL_DETECTIONS:-false} STORE_RAW_PAYLOAD: ${STORE_RAW_PAYLOAD:-false} RATE_LIMIT_WINDOW_MS: ${RATE_LIMIT_WINDOW_MS:-900000} RATE_LIMIT_MAX_REQUESTS: ${RATE_LIMIT_MAX_REQUESTS:-1000} SECURITY_LOG_DIR: /app/logs ports: - "3002:3001" volumes: - ./server/logs:/app/logs - ./debug_logs:/app/debug_logs - ./uploads:/app/uploads networks: - drone-network depends_on: postgres: condition: service_healthy redis: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/api/health"] interval: 30s timeout: 10s retries: 3 # Frontend React Application frontend: build: context: ./client dockerfile: Dockerfile args: VITE_BASE_PATH: ${VITE_BASE_PATH:-/} VITE_API_URL: ${VITE_API_URL:-} NODE_ENV: production container_name: drone-detection-frontend restart: unless-stopped ports: - "3001:80" networks: - drone-network depends_on: - backend healthcheck: test: ["CMD", "curl", "-f", "http://localhost:80"] interval: 30s timeout: 10s retries: 3 # Management Portal management: build: context: ./management dockerfile: Dockerfile args: VITE_API_URL: ${VITE_API_URL:-/api} container_name: drone-detection-management restart: unless-stopped ports: - "3003:80" networks: - drone-network depends_on: - backend healthcheck: test: ["CMD", "curl", "-f", "http://localhost:80"] interval: 30s timeout: 10s retries: 3 # Nginx Reverse Proxy (Production) nginx: image: nginx:alpine container_name: drone-detection-nginx restart: unless-stopped ports: - "8080:80" - "8443:443" volumes: - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf - ./docker/ssl:/etc/nginx/ssl - ./client/dist:/usr/share/nginx/html networks: - drone-network depends_on: - frontend - backend profiles: - production # Python Drone Simulator (Optional) simulator: build: context: . dockerfile: docker/simulator/Dockerfile container_name: drone-detection-simulator restart: "no" environment: API_URL: http://backend:3001/api networks: - drone-network depends_on: - backend profiles: - simulation command: python drone_simulator.py --devices 5 --duration 3600 # Data Retention Service (Microservice) data-retention: build: context: ./data-retention-service dockerfile: Dockerfile container_name: drone-detection-data-retention restart: unless-stopped environment: DB_HOST: postgres DB_PORT: 5432 DB_NAME: ${DB_NAME:-drone_detection} DB_USER: ${DB_USER:-postgres} DB_PASSWORD: ${DB_PASSWORD:-your_secure_password} NODE_ENV: ${NODE_ENV:-production} IMMEDIATE_CLEANUP: ${IMMEDIATE_CLEANUP:-false} networks: - drone-network depends_on: postgres: condition: service_healthy healthcheck: test: ["CMD", "node", "healthcheck.js"] interval: 30s timeout: 10s retries: 3 # Resource limits for lightweight container deploy: resources: limits: memory: 128M reservations: memory: 64M # Health Probe Simulator (Continuous Device Heartbeats) healthprobe: build: context: . dockerfile: Dockerfile.healthprobe container_name: drone-detection-healthprobe restart: unless-stopped environment: PROBE_FAILRATE: ${PROBE_FAILRATE:-30} PROBE_INTERVAL_SECONDS: ${PROBE_INTERVAL_SECONDS:-60} API_BASE_URL: http://backend:3001/api networks: - drone-network depends_on: backend: condition: service_healthy profiles: - healthprobe volumes: postgres_data: driver: local redis_data: driver: local networks: drone-network: driver: bridge