# Docker Compose configuration for Stream Processing Django Application
# Optimized for production with enhanced security and performance

version: '3.8'

services:
  # PostgreSQL database service
  # Primary database for storing application data
  db:
    image: postgres:17-alpine
    container_name: stream_postgres
    restart: unless-stopped
    environment:
      # Database configuration from environment variables
      POSTGRES_DB: ${DB_NAME:-stream_db}
      POSTGRES_USER: ${DB_USER:-postgres}
      POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres}
      # Performance tuning
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
    volumes:
      # Persistent storage for database data
      - postgres_data:/var/lib/postgresql/data
      # Custom initialization scripts
      - ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
      # PostgreSQL configuration for performance
      - ./docker/postgres/postgresql.conf:/etc/postgresql/postgresql.conf 
    networks:
      - stream_network
    healthcheck:
      # Health check to ensure database is ready
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres}"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 30s 
    security_opt:
      - no-new-privileges:true

  # Redis service for Celery message broker
  # Used for task queue management and caching
  redis:
    image: redis:7.4-alpine
    container_name: stream_redis
    restart: unless-stopped 
    volumes:
      # Persistent storage for Redis data
      - redis_data:/data
      # Redis configuration for security and performance
      - ./docker/redis/redis.conf:/usr/local/etc/redis/redis.conf
    networks:
      - stream_network
    command: |
      sh -c '
        # Fix permissions for Redis data directory
        chown -R 1000:1000 /data
        chmod -R 755 /data
        # Start Redis as root (will drop privileges internally)
        exec redis-server /usr/local/etc/redis/redis.conf
      '
    healthcheck:
      # Health check for Redis availability
      test: ["CMD", "redis-cli", "ping"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 10s 
    security_opt:
      - no-new-privileges:true

  # Main Django web application
  # Handles web interface and API endpoints
  web:
    build:
      context: .
      dockerfile: docker/web.Dockerfile
      target: ${BUILD_TARGET:-development}
      args:
        - BUILDKIT_INLINE_CACHE=1
    container_name: stream_web
    restart: unless-stopped
    ports:
      - "8003:8000"
    volumes: 
      - ./src:/app
      # Media files volume (bind mount to local directory)
      - ./src/media:/app/media
      # Logs volume (bind mount to local directory)
      - ./src/logs:/app/logs
      # Static files volume (for nginx in production)
      - static_data:/app/staticfiles
      # Development code volume (only in development)
      # - ./src:/app:${VOLUME_MODE:-rw}
    environment:
      # Environment variables for Django configuration
      - DEBUG=${DEBUG:-False}
      - SECRET_KEY=${SECRET_KEY}
      - DB_NAME=${DB_NAME:-stream_db}
      - DB_USER=${DB_USER:-postgres}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_HOST=db
      - DB_PORT=5432
      - REDIS_URL=redis://redis:6379/0
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
      - DEFAULT_ADMIN_USERNAME=${DEFAULT_ADMIN_USERNAME:-admin}
      - DEFAULT_ADMIN_EMAIL=${DEFAULT_ADMIN_EMAIL:-admin@streamprocessor.com}
      - DEFAULT_ADMIN_PASSWORD=${DEFAULT_ADMIN_PASSWORD}
      # Security settings
      - SECURE_SSL_REDIRECT=${SECURE_SSL_REDIRECT:-True}
      - SECURE_PROXY_SSL_HEADER=HTTP_X_FORWARDED_PROTO,https
      - SESSION_COOKIE_SECURE=${SESSION_COOKIE_SECURE:-True}
      - CSRF_COOKIE_SECURE=${CSRF_COOKIE_SECURE:-True}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - stream_network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s 
    security_opt:
      - no-new-privileges:true
    command: >
      sh -c "python manage.py makemigrations &&
             python manage.py migrate &&
             python manage.py runserver 0.0.0.0:8000" 

  # Celery worker for background tasks
  # Handles stream processing, jingle detection, and notifications
  celery_worker:
    build:
      context: .
      dockerfile: docker/worker.Dockerfile
      args:
        - BUILDKIT_INLINE_CACHE=1
    container_name: stream_celery_worker
    restart: unless-stopped
    volumes:
      # Media files volume (bind mount to local directory)
      - ./src/media:/app/media
      # Logs volume (bind mount to local directory)
      - ./src/logs:/app/logs
      # Development code volume (only in development)
      - ./src:/app:${VOLUME_MODE:-rw}
    environment:
      # Same environment variables as web service
      - DEBUG=${DEBUG:-False}
      - SECRET_KEY=${SECRET_KEY}
      - DB_NAME=${DB_NAME:-stream_db}
      - DB_USER=${DB_USER:-postgres}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_HOST=db
      - DB_PORT=5432
      - REDIS_URL=redis://redis:6379/0
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
      # Celery worker optimization
      - CELERY_WORKER_CONCURRENCY=${CELERY_WORKER_CONCURRENCY:-4}
      - CELERY_WORKER_PREFETCH_MULTIPLIER=${CELERY_WORKER_PREFETCH_MULTIPLIER:-1}
      - CELERY_TASK_ACKS_LATE=True
      - CELERY_WORKER_DISABLE_RATE_LIMITS=True
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
      web:
        condition: service_healthy
    networks:
      - stream_network
    healthcheck:
      test: ["CMD", "celery", "-A", "core", "inspect", "ping"]
      interval: 60s
      timeout: 30s
      retries: 3
      start_period: 120s 
    security_opt:
      - no-new-privileges:true
    command: sh -c "celery -A core worker --loglevel=info --concurrency=${CELERY_WORKER_CONCURRENCY:-4} --prefetch-multiplier=${CELERY_WORKER_PREFETCH_MULTIPLIER:-1}"

  # Celery beat scheduler for periodic tasks
  # Manages scheduled tasks like health checks and cleanup
  celery_beat:
    build:
      context: .
      dockerfile: docker/worker.Dockerfile
      args:
        - BUILDKIT_INLINE_CACHE=1
    container_name: stream_celery_beat
    restart: unless-stopped
    volumes:
      # Logs volume (bind mount to local directory)
      - ./logs:/app/logs
      # Beat schedule volume (persistent)
      - beat_data:/app/beat
      # Development code volume (only in development)
      - ./src:/app:${VOLUME_MODE:-rw}
    environment:
      # Same environment variables as other services
      - DEBUG=${DEBUG:-False}
      - SECRET_KEY=${SECRET_KEY}
      - DB_NAME=${DB_NAME:-stream_db}
      - DB_USER=${DB_USER:-postgres}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_HOST=db
      - DB_PORT=5432
      - REDIS_URL=redis://redis:6379/0
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
      web:
        condition: service_healthy
    networks:
      - stream_network
    healthcheck:
      test: ["CMD", "celery", "-A", "core", "inspect", "active"]
      interval: 60s
      timeout: 30s
      retries: 3
      start_period: 120s
    security_opt:
      - no-new-privileges:true
    command: sh -c "celery -A core beat --loglevel=info --schedule=/app/beat/celerybeat-schedule"

  # Flower service for monitoring Celery tasks
  # Provides web interface for task monitoring
  flower:
    build:
      context: .
      dockerfile: docker/worker.Dockerfile
      args:
        - BUILDKIT_INLINE_CACHE=1
    container_name: stream_flower
    restart: unless-stopped
    ports:
      - "5556:5555"
    environment:
      # Celery broker configuration for Flower
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
      # Flower authentication (optional)
      - FLOWER_BASIC_AUTH=${FLOWER_BASIC_AUTH:-admin:flower123}
    depends_on:
      redis:
        condition: service_healthy
      celery_worker:
        condition: service_healthy
    networks:
      - stream_network
    healthcheck:
      test: ["CMD", "curl", "-f", "-u", "admin:flower123", "http://localhost:5555/"]
      interval: 60s
      timeout: 10s
      retries: 3
      start_period: 30s 
    security_opt:
      - no-new-privileges:true
    command: sh -c "celery -A core flower --port=5555 --basic_auth=${FLOWER_BASIC_AUTH:-admin:flower123}"

# Named volumes for persistent data storage
volumes:
  # PostgreSQL database data
  postgres_data:
    driver: local
  # Redis data storage
  redis_data:
    driver: local
  # Stream files storage
  stream_data:
    driver: local
  # Jingle files storage
  jingle_data:
    driver: local
  # Application logs volume
  logs_data:
    driver: local
  # Media files volume
  media_data:
    driver: local
  # Static files volume
  static_data:
    driver: local
  # Celery beat schedule volume
  beat_data:
    driver: local

# Network configuration for service communication
networks:
  stream_network:
    driver: bridge
