256 lines
8.2 KiB
YAML
256 lines
8.2 KiB
YAML
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:
|