name: east-guilan services: traefik: image: traefik:v2.11 entrypoint: ["/bin/sh", "/traefik-entrypoint.sh"] command: - --providers.docker=true - --providers.docker.exposedbydefault=false - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --entrypoints.web.http.redirections.entryPoint.to=websecure - --entrypoints.web.http.redirections.entryPoint.scheme=https - --certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL} - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json - --certificatesresolvers.le.acme.httpchallenge=true - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web # 🔹 Enable Prometheus metrics - --metrics.prometheus=true - --metrics.prometheus.addEntryPointsLabels=true - --metrics.prometheus.addRoutersLabels=true - --metrics.prometheus.addServicesLabels=true # 🔹 Expose metrics on a separate entrypoint (port 8082) - --entrypoints.metrics.address=:8082 - --metrics.prometheus.entryPoint=metrics # (optional) dashboard if you want it later: - --api.dashboard=true # Route /metrics on api.east-guilan-ce.ir to web:8000 - traefik.http.routers.metrics.rule=Host(`api.east-guilan-ce.ir`) && Path(`/metrics`) - traefik.http.routers.metrics.entrypoints=websecure - traefik.http.routers.metrics.tls.certresolver=le - traefik.http.services.metrics.loadbalancer.server.port=8000 ports: - "80:80" - "443:443" volumes: - ./traefik/entrypoint.sh:/traefik-entrypoint.sh:ro - ./certs:/certs:ro - traefik_letsencrypt:/letsencrypt - /var/run/docker.sock:/var/run/docker.sock:ro db: image: postgres:16-alpine environment: POSTGRES_DB: ${DB_NAME} POSTGRES_USER: ${DB_USER} POSTGRES_PASSWORD: ${DB_PASSWORD} healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME} -h 127.0.0.1"] interval: 10s timeout: 5s retries: 10 volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"] healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "PING"] interval: 10s timeout: 5s retries: 10 volumes: - redis_data:/data web: build: context: ./backend dockerfile: Dockerfile env_file: .env environment: DJANGO_SETTINGS_MODULE: ${DJANGO_SETTINGS_MODULE} REDIS_URL: ${REDIS_URL} PROMETHEUS_MULTIPROC_DIR: /tmp/prometheus tmpfs: - /tmp/prometheus depends_on: db: condition: service_healthy redis: condition: service_healthy volumes: - django_static:/app/staticfiles - django_media:/app/media command: > gunicorn config.wsgi:application --bind 0.0.0.0:8000 --workers=${GUNICORN_WORKERS:-3} --threads=${GUNICORN_THREADS:-2} --timeout=${GUNICORN_TIMEOUT:-120} labels: - traefik.enable=true - traefik.http.routers.api.rule=Host(`api.east-guilan-ce.ir`) && PathPrefix(`/api`) - traefik.http.routers.api.entrypoints=websecure - traefik.http.routers.api.tls.certresolver=le - traefik.http.routers.api.priority=10 - traefik.http.services.api.loadbalancer.server.port=8000 - traefik.http.routers.admin.rule=Host(`api.east-guilan-ce.ir`) && PathPrefix(`/admin`) - traefik.http.routers.admin.entrypoints=websecure - traefik.http.routers.admin.tls.certresolver=le - traefik.http.routers.admin.priority=10 worker: build: context: ./backend dockerfile: Dockerfile env_file: .env depends_on: db: condition: service_healthy redis: condition: service_healthy command: celery -A config.services.celery worker --loglevel=INFO volumes: - django_media:/app/media beat: build: context: ./backend dockerfile: Dockerfile env_file: .env depends_on: - worker command: celery -A config.services.celery beat --loglevel=INFO volumes: - django_media:/app/media frontend: build: context: ./frontend dockerfile: Dockerfile args: NEXT_PUBLIC_API_BASE: https://api.east-guilan-ce.ir labels: - traefik.enable=true - traefik.http.routers.frontend.rule=Host(`${NEXT_HOST}`) - traefik.http.routers.frontend.entrypoints=websecure - traefik.http.routers.frontend.tls.certresolver=le - traefik.http.services.frontend.loadbalancer.server.port=80 static: image: nginx:1.27-alpine volumes: - ./nginx-static.conf:/etc/nginx/conf.d/default.conf:ro - django_static:/var/www/static:ro - django_media:/var/www/media:ro labels: - traefik.enable=true # higher priority so /static & /media never reach backend - traefik.http.routers.static.rule=Host(`api.east-guilan-ce.ir`) && PathPrefix(`/static`) - traefik.http.routers.static.entrypoints=websecure - traefik.http.routers.static.tls.certresolver=le - traefik.http.routers.static.priority=20 - traefik.http.services.static.loadbalancer.server.port=80 - traefik.http.routers.media.rule=Host(`api.east-guilan-ce.ir`) && PathPrefix(`/media`) - traefik.http.routers.media.entrypoints=websecure - traefik.http.routers.media.tls.certresolver=le - traefik.http.routers.media.priority=20 uptime: image: louislam/uptime-kuma:1 restart: unless-stopped volumes: ["./data/uptime:/app/data"] labels: - traefik.enable=true - traefik.http.routers.kuma.rule=Host(`uptime.east-guilan-ce.ir`) - traefik.http.routers.kuma.entrypoints=websecure - traefik.http.routers.kuma.tls.certresolver=le - traefik.http.services.kuma.loadbalancer.server.port=3001 node_exporter: image: prom/node-exporter:v1.9.1 restart: unless-stopped ports: ["9100:9100"] volumes: - /:/host:ro,rslave - /proc:/host/proc:ro - /sys:/host/sys:ro - /run/udev:/host/run/udev:ro command: - --path.rootfs=/host - --path.procfs=/host/proc - --path.sysfs=/host/sys - --path.udev.data=/host/run/udev/data postgres_exporter: image: quay.io/prometheuscommunity/postgres-exporter:v0.15.0 restart: unless-stopped environment: - DATA_SOURCE_NAME=postgresql://${DB_USER}:${DB_PASSWORD}@db:5432/${DB_NAME}?sslmode=disable depends_on: db: condition: service_healthy redis_exporter: image: oliver006/redis_exporter:v1.62.0 restart: unless-stopped command: - '--redis.addr=redis://redis:6379' - '--redis.password=${REDIS_PASSWORD}' grafana: image: grafana/grafana restart: unless-stopped labels: - traefik.enable=true - traefik.http.routers.grafana.rule=Host(`grafana.east-guilan-ce.ir`) - traefik.http.routers.grafana.entrypoints=websecure - traefik.http.routers.grafana.tls.certresolver=le - traefik.http.services.grafana.loadbalancer.server.port=3000 volumes: - grafana_data:/var/lib/grafana - ./grafana-datasources.yml:/etc/grafana/provisioning/datasources/datasource.yml:ro environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=changeMeNow - GF_USERS_ALLOW_SIGN_UP=false alertmanager: image: prom/alertmanager restart: unless-stopped volumes: - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro command: --config.file=/etc/alertmanager/alertmanager.yml prometheus: image: prom/prometheus volumes: - prometheus_data:/prometheus - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro restart: unless-stopped labels: - traefik.enable=true - traefik.http.routers.prom.rule=Host(`prometheus.east-guilan-ce.ir`) - traefik.http.routers.prom.entrypoints=websecure - traefik.http.routers.prom.tls.certresolver=le - traefik.http.services.prom.loadbalancer.server.port=9090 volumes: traefik_letsencrypt: postgres_data: redis_data: django_media: django_static: prometheus_data: grafana_data: