# Production Docker Compose
# Variables are read from .env file

services:
  traefik:
    image: traefik:v3.0
    container_name: ${PROJECT_NAME}_traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    environment:
      - HETZNER_API_KEY=${HETZNER_DNS_API_TOKEN}
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./deploy/traefik/traefik.yml:/etc/traefik/traefik.yml:ro
      - ./deploy/traefik/dynamic:/etc/traefik/dynamic:ro
      - traefik_letsencrypt:/letsencrypt
      - traefik_logs:/var/log/traefik
    healthcheck:
      test: ["CMD", "traefik", "healthcheck"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - app
    labels:
      - "traefik.enable=true"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  backend:
    image: ${DOCKER_REGISTRY}/${GITHUB_REPOSITORY}-backend:${IMAGE_TAG}
    container_name: ${PROJECT_NAME}_backend
    restart: unless-stopped
    environment:
      - DATABASE_URL=postgresql+asyncpg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
      - SECRET_KEY=${SECRET_KEY}
      - ENVIRONMENT=${ENVIRONMENT}
      - ALLOWED_HOSTS=${ALLOWED_HOSTS}
      - BASE_DOMAIN=${DOMAIN}
      - PYTHONPATH=/app/{{ backend_path }}/src
      {% if use_redis %}- REDIS_URL=${REDIS_URL}
      {% endif %}
    depends_on:
      traefik:
        condition: service_healthy
      db:
        condition: service_healthy
      {% if use_redis %}redis:
        condition: service_healthy
      {% endif %}
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    networks:
      - app
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.backend.loadbalancer.server.port=8000"
      - "traefik.http.routers.backend-api.rule=Host(`${DOMAIN}`) && PathPrefix(`/api`)"
      - "traefik.http.routers.backend-api.entrypoints=websecure"
      - "traefik.http.routers.backend-api.tls.certresolver=letsencrypt-dns"
      - "traefik.http.routers.backend-api.priority=20"
      - "traefik.http.routers.backend-graphql.rule=Host(`${DOMAIN}`) && PathPrefix(`/graphql`)"
      - "traefik.http.routers.backend-graphql.entrypoints=websecure"
      - "traefik.http.routers.backend-graphql.tls.certresolver=letsencrypt-dns"
      - "traefik.http.routers.backend-graphql.priority=20"
      - "traefik.http.routers.backend-health.rule=Host(`${DOMAIN}`) && Path(`/health`)"
      - "traefik.http.routers.backend-health.entrypoints=websecure"
      - "traefik.http.routers.backend-health.tls.certresolver=letsencrypt-dns"
      - "traefik.http.routers.backend-health.priority=20"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  frontend:
    image: ${DOCKER_REGISTRY}/${GITHUB_REPOSITORY}-frontend:${IMAGE_TAG}
    container_name: ${PROJECT_NAME}_frontend
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:80/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - app
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.frontend.loadbalancer.server.port=80"
      - "traefik.http.routers.frontend.rule=Host(`${DOMAIN}`) || Host(`www.${DOMAIN}`)"
      - "traefik.http.routers.frontend.entrypoints=websecure"
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt-dns"
      - "traefik.http.routers.frontend.priority=10"
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  db:
    image: postgres:16-alpine
    container_name: ${PROJECT_NAME}_db
    restart: unless-stopped
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - /mnt/data/postgres:/var/lib/postgresql/data
      - ./backups:/backups
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  {% if use_redis %}redis:
    image: redis:7-alpine
    container_name: ${PROJECT_NAME}_redis
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
  {% endif %}

volumes:
  postgres_data:
    driver: local
  {% if use_redis %}redis_data:
    driver: local
  {% endif %}traefik_letsencrypt:
    driver: local
  traefik_logs:
    driver: local

networks:
  app:
    name: ${PROJECT_NAME}_network
