version: '3.8'

services:
  traefik:
    image: traefik:v3.0
    command:
      # API and dashboard
      - --api.dashboard=true
      - --api.insecure=false
      
      # Docker provider
      - --providers.docker.swarmMode=true
      - --providers.docker.exposedbydefault=false
      - --providers.docker.network=traefik-public
      
      # Entry points
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entrypoints.web.http.redirections.entrypoint.scheme=https
      
      # SSL/TLS configuration
      - --certificatesresolvers.letsencrypt.acme.email=admin@yourdomain.com
      - --certificatesresolvers.letsencrypt.acme.storage=/certificates/acme.json
      - --certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web
      
      # Security headers
      - --entrypoints.websecure.http.middlewares=security-headers@file
      - --entrypoints.websecure.http.middlewares=rate-limit@file
      
      # Logging
      - --log.level=INFO
      - --accesslog=true
      - --accesslog.filepath=/var/log/traefik/access.log
      - --accesslog.format=json
      
      # Metrics
      - --metrics.prometheus=true
      - --metrics.prometheus.addEntryPointsLabels=true
      - --metrics.prometheus.addServicesLabels=true
      
      # Health checks
      - --ping=true
      - --ping.entryPoint=web
      
      # File provider for static configuration
      - --providers.file.directory=/etc/traefik/dynamic
      - --providers.file.watch=true
      
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Dashboard (internal only)
      
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - traefik-certificates:/certificates
      - traefik-logs:/var/log/traefik
      - ./dynamic:/etc/traefik/dynamic:ro
      - ./traefik.yml:/etc/traefik/traefik.yml:ro
      
    networks:
      - traefik-public
      
    deploy:
      placement:
        constraints:
          - node.role == manager
        preferences:
          - spread: node.labels.zone
      replicas: 2
      resources:
        limits:
          memory: 512M
          cpus: '0.5'
        reservations:
          memory: 256M
          cpus: '0.25'
      labels:
        # Traefik dashboard
        - "traefik.enable=true"
        - "traefik.http.routers.traefik-dashboard.rule=Host(`traefik.yourdomain.com`)"
        - "traefik.http.routers.traefik-dashboard.entrypoints=websecure"
        - "traefik.http.routers.traefik-dashboard.tls.certresolver=letsencrypt"
        - "traefik.http.routers.traefik-dashboard.service=api@internal"
        - "traefik.http.routers.traefik-dashboard.middlewares=auth@file"
        
        # Health check
        - "traefik.http.routers.traefik-health.rule=PathPrefix(`/ping`)"
        - "traefik.http.routers.traefik-health.entrypoints=web"
        - "traefik.http.routers.traefik-health.service=ping@internal"
        
        # Metrics
        - "traefik.http.routers.traefik-metrics.rule=Host(`traefik.yourdomain.com`) && PathPrefix(`/metrics`)"
        - "traefik.http.routers.traefik-metrics.entrypoints=websecure"
        - "traefik.http.routers.traefik-metrics.tls.certresolver=letsencrypt"
        - "traefik.http.routers.traefik-metrics.service=prometheus@internal"
        - "traefik.http.routers.traefik-metrics.middlewares=auth@file"
        
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
      
      update_config:
        parallelism: 1
        delay: 10s
        order: start-first
        
      rollback_config:
        parallelism: 1
        delay: 5s
        order: stop-first

volumes:
  traefik-certificates:
    driver: local
  traefik-logs:
    driver: local

networks:
  traefik-public:
    external: true
