# ==============================================================================
# ENTERPRISE DOCKER COMPOSE CONFIGURATION
# ==============================================================================
# Docker Compose configuration for Adtlas DAI Management System
# This file defines all services needed for the application

# ==============================================================================
# NETWORKS
# ==============================================================================
# Custom networks for service isolation and Communication
networks:
  frontend:
    driver: bridge
    # ipam:
    #   config:
    #     - subnet: 172.20.0.0/16
  backend:
    driver: bridge
    internal: true
    # ipam:
    #   config:
    #     - subnet: 172.20.0.0/16
  monitoring:
    driver: bridge
    # ipam:
    #   config:
    #     - subnet: 172.20.0.0/16


# ==============================================================================
# SERVICES
# ==============================================================================
# Services are the individual containers that make up your application
services:
  # ==============================================================================
  # DATABASE SERVICES
  # ==============================================================================
  # PostgreSQL Database Service
  # Configuration for Database Service
  db:
    # Use the latest MySQL image from Docker Hub
    image: postgres:15-alpine
    # Assign a specific name to the container
    container_name: adtlas_db  
    # Always restart the container if it stops
    restart: unless-stopped
    # ports:
    #   - "5432:5432" 
    volumes:
      - postgres_data:/var/lib/postgresql/data/
      - postgres_backups:/backups
      - ./docker/postgres/postgresql.conf:/etc/postgresql/postgresql.conf:ro
      - ./docker/postgres/init-scripts:/docker-entrypoint-initdb.d:ro
      - ./docker/postgres/init-scripts/init.sql:/docker-entrypoint-initdb.d/init.sql
    environment:
      POSTGRES_DB: ${POSTGRES_DB:-adtlas_db}
      POSTGRES_USER: ${POSTGRES_USER:-adtlas_user}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-adtlas_password}
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C"
      POSTGRES_HOST_AUTH_METHOD: trust
      PGDATA: /var/lib/postgresql/data/pgdata 
    command: >
      postgres
      -c config_file=/etc/postgresql/postgresql.conf
      -c log_statement=all
      -c log_destination=stderr
    # Add health check configuration for Database container
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-adtlas_user} -d ${POSTGRES_DB:-adtlas_db}"]
      interval: 10s # Health check will run every 10 seconds
      timeout: 5s # If health check command doesn't return within 5 seconds, it's considered a failure
      retries: 5 # Container marked as unhealthy after 5 consecutive failures
      start_period: 30s # Health check will start after 30 seconds
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          memory: 2G
          cpus: '1.0'
        reservations:
          memory: 512M
          cpus: '0.25'
    # Memory and swap configuration to address kernel warnings
    mem_limit: 2G
    memswap_limit: 2G
    mem_swappiness: 10
    # Attach the service to a custom network
    networks:
      - backend
  
  # ==============================================================================
  # CACHE & MESSAGE BROKER
  # ==============================================================================
  # Redis Service for Celery
  redis:
    image: redis:7-alpine
    container_name: adtlas_redis
    restart: unless-stopped
    networks:
      - backend
    # ports:
    #   - "6379:6379"
    volumes:
      - redis_data:/data
      - ./docker/redis/redis.conf:/usr/local/etc/redis/redis.conf:ro
    command: redis-server /usr/local/etc/redis/redis.conf
    environment:
      REDIS_PASSWORD: ${REDIS_PASSWORD:-}
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'
        reservations:
          memory: 128M
          cpus: '0.1'
    # Memory and swap configuration to address kernel warnings
    mem_limit: 512M
    memswap_limit: 512M
    mem_swappiness: 10

  # ==============================================================================
  # APPLICATION SERVICES
  # ==============================================================================
  # Django Web Application
  web:
    build:
      context: .
      dockerfile: docker/web/Dockerfile 
      target: production
      args:
        BUILD_DATE: ${BUILD_DATE:-}
        VCS_REF: ${VCS_REF:-}
        VERSION: ${VERSION:-latest}
    container_name: adtlas_web
    restart: unless-stopped
    networks:
      - frontend
      - backend
    command: >
      sh -c "python manage.py migrate &&
            python manage.py collectstatic --noinput &&
            python manage.py runserver 0.0.0.0:8000"
    volumes:
      - ./src:/app
      - media_volume:/app/media
      - static_volume:/app/static
      - logs_volume:/app/logs
      - ./docker/nginx/ssl:/ssl:ro
    # ports:
    #   - "8000:8000"
    environment:  
      - DJANGO_SETTINGS_MODULE=core.settings
      - DEBUG=${DEBUG:-0}
      - SECRET_KEY=${SECRET_KEY}
      - DATABASE_URL=postgresql://${POSTGRES_USER:-adtlas_user}:${POSTGRES_PASSWORD:-adtlas_password}@db:5432/${POSTGRES_DB:-adtlas_db}
      - REDIS_URL=redis://redis:6379/0
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
      - ALLOWED_HOSTS=${ALLOWED_HOSTS:-localhost,127.0.0.1}
      - CSRF_TRUSTED_ORIGINS=${CSRF_TRUSTED_ORIGINS:-http://localhost:8000}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          memory: 1G
          cpus: '1.0'
        reservations:
          memory: 256M
          cpus: '0.25'
    # Memory and swap configuration to address kernel warnings
    mem_limit: 1G
    memswap_limit: 1G
    mem_swappiness: 10 

  # ==============================================================================
  # TASK PROCESSING
  # ==============================================================================
  # # Celery Worker for Background Tasks
  # celery_worker:
  #   build:
  #     context: .
  #     dockerfile: docker/web/Dockerfile
  #     target: production
  #   container_name: adtlas_celery_worker
  #   restart: unless-stopped
  #   networks:
  #     - backend
  #   volumes:
  #     - ./src:/app
  #     - media_volume:/app/media
  #     - logs_volume:/app/logs
  #   command: > 
  #     celery -A core worker 
  #     --loglevel=info 
  #     --concurrency=4
  #     --max-tasks-per-child=1000
  #     --time-limit=300
  #     --soft-time-limit=240
  #     --prefetch-multiplier=1
  #   environment: 
  #     - DJANGO_SETTINGS_MODULE=core.settings
  #     - DEBUG=${DEBUG:-1}
  #     - SECRET_KEY=${SECRET_KEY}
  #     - DATABASE_URL=postgresql://${POSTGRES_USER:-adtlas_user}:${POSTGRES_PASSWORD:-adtlas_password}@db:5432/${POSTGRES_DB:-adtlas_db}
  #     - 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
  #   healthcheck:
  #     test: ["CMD", "celery", "-A", "core", "inspect", "ping"]
  #     interval: 30s
  #     timeout: 10s
  #     retries: 3
  #     start_period: 60s
  #   security_opt:
  #     - no-new-privileges:true
  #   deploy:
  #     resources:
  #       limits:
  #         memory: 1G
  #         cpus: '1.0'
  #       reservations:
  #         memory: 256M
  #         cpus: '0.25'

  # # Celery Beat for Scheduled Tasks
  # celery_beat:
  #   build:
  #     context: .
  #     dockerfile: docker/web/Dockerfile
  #     target: production
  #   container_name: adtlas_celery_beat
  #   restart: unless-stopped
  #   networks:
  #     - backend    
  #   volumes:
  #     - ./src:/app
  #     - logs_volume:/app/logs
  #     - celery_beat_data:/celerybeat-schedule
  #   command: >
  #     celery -A core beat 
  #     --loglevel=info 
  #     --scheduler django_celery_beat.schedulers:DatabaseScheduler
  #   environment:
  #     - DJANGO_SETTINGS_MODULE=core.settings
  #     - DEBUG=${DEBUG:-1} 
  #     - SECRET_KEY=${SECRET_KEY} 
  #     - DATABASE_URL=postgresql://${POSTGRES_USER:-adtlas_user}:${POSTGRES_PASSWORD:-adtlas_password}@db:5432/${POSTGRES_DB:-adtlas_db}
  #     - 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
  #   security_opt:
  #     - no-new-privileges:true
  #   deploy:
  #     resources:
  #       limits:
  #         memory: 256M
  #         cpus: '0.5'
  #       reservations:
  #         memory: 64M
  #         cpus: '0.1'
  #   # Memory and swap configuration to address kernel warnings
  #   mem_limit: 256M
  #   memswap_limit: 256M
  #   mem_swappiness: 10 

  # ==============================================================================
  # REVERSE PROXY & LOAD BALANCER
  # ==============================================================================
  # Nginx Reverse Proxy 
  nginx:
    build:
      context: .
      dockerfile: docker/nginx/Dockerfile
    container_name: adtlas_nginx
    restart: unless-stopped
    networks:
      - frontend
    ports:
      - "8082:80"
      - "8443:443"
    volumes:
      - ./docker/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./docker/nginx/conf.d:/etc/nginx/conf.d:ro
      - ./docker/nginx/ssl:/etc/nginx/ssl:ro
      - static_volume:/var/www/static:ro
      - media_volume:/var/www/media:ro
      - logs_volume:/var/log/nginx 
    depends_on: 
      web:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          memory: 256M
          cpus: '0.5'
        reservations:
          memory: 64M
          cpus: '0.1'
    # Memory and swap configuration to address kernel warnings
    mem_limit: 256M
    memswap_limit: 256M
    mem_swappiness: 10

  # ==============================================================================
  # MONITORING & OBSERVABILITY
  # ==============================================================================
  # # Prometheus for Monitoring
  # prometheus:
  #   image: prom/prometheus:latest
  #   container_name: adtlas_prometheus
  #   restart: unless-stopped
  #   networks:
  #     - monitoring
  #     - backend
  #   ports:
  #     - "9091:9090"
  #   volumes:
  #     - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
  #     - prometheus_data:/prometheus
  #   command:
  #     - '--config.file=/etc/prometheus/prometheus.yml'
  #     - '--storage.tsdb.path=/prometheus'
  #     - '--web.console.libraries=/etc/prometheus/console_libraries'
  #     - '--web.console.templates=/etc/prometheus/consoles'
  #     - '--storage.tsdb.retention.time=30d'
  #     - '--web.enable-lifecycle'
  #   healthcheck:
  #     test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
  #     # test: ["CMD-SHELL", "curl -f http://localhost:9090/-/healthy || exit 1"]
  #     interval: 30s
  #     timeout: 10s
  #     retries: 3
  #     start_period: 30s
  #   security_opt:
  #     - no-new-privileges:true
  #   deploy:
  #     resources:
  #       limits:
  #         memory: 512M
  #         cpus: '0.5'
  #       reservations:
  #         memory: 128M
  #         cpus: '0.1'
  #   # Memory and swap configuration to address kernel warnings
  #   mem_limit: 512M
  #   memswap_limit: 512M
  #   mem_swappiness: 10

  # # Grafana for Visualization
  # grafana:
  #   image: grafana/grafana:latest
  #   container_name: adtlas_grafana
  #   restart: unless-stopped
  #   networks:
  #     - monitoring
  #     - frontend
  #   ports:
  #     - "3001:3000"
  #   volumes:
  #     - grafana_data:/var/lib/grafana
  #     - ./docker/grafana/provisioning:/etc/grafana/provisioning:ro
  #     - ./docker/grafana/dashboards:/var/lib/grafana/dashboards:ro
  #   environment:
  #     - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD:-admin123}
  #     - GF_USERS_ALLOW_SIGN_UP=false
  #     - GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
  #   depends_on:
  #     prometheus:
  #       condition: service_healthy 
  #   security_opt:
  #     - no-new-privileges:true
  #   deploy:
  #     resources:
  #       limits:
  #         memory: 256M
  #         cpus: '0.5'
  #       reservations:
  #         memory: 64M
  #         cpus: '0.1'
  #   # Memory and swap configuration to address kernel warnings
  #   mem_limit: 256M
  #   memswap_limit: 256M
  #   mem_swappiness: 10

# ==============================================================================
# PERSISTENT VOLUMES
# ==============================================================================
# Named Volumes for Data Persistence
volumes:
  postgres_data:
    driver: local
  postgres_backups:
    driver: local
  redis_data:
    driver: local
  media_volume:
    driver: local
  static_volume:
    driver: local 
  logs_volume:
    driver: local
  celery_beat_data:
    driver: local
  prometheus_data:
    driver: local
  grafana_data:
    driver: local

