services: # ─────────────────────────────────────────────────────────────────────────── # 1. .NET API # ─────────────────────────────────────────────────────────────────────────── api: container_name: opencand_api restart: unless-stopped image: git.ivanch.me/ivanch/opencand.api:latest ports: - "5100:8080" environment: ASPNETCORE_ENVIRONMENT: "Production" DatabaseSettings__ConnectionString: "Host=db;Port=5432;Database=opencand;Username=root;Password=root" FotosSettings__ApiBasePath: "https://api.opencand.ivanch.me/assets/fotos" volumes: - ./fotos_cand:/app/fotos_cand logging: driver: "json-file" options: max-size: "10m" max-file: "3" labels: "service=api" labels: - "promtail.enable=true" - "promtail.job=opencand-api" # ─────────────────────────────────────────────────────────────────────────── # 2. React + Vite Front‐end # ─────────────────────────────────────────────────────────────────────────── frontend: container_name: opencand_frontend restart: unless-stopped image: git.ivanch.me/ivanch/opencand.ui:latest ports: - "5110:80" depends_on: - api # ─────────────────────────────────────────────────────────────────────────── # 3. ETL (Optional: runs once at startup) # # If you want the ETL to run on every compose up, give it restart: "no" or # some other policy. It will run, then exit. # # If you instead prefer to run ETL manually or via host cron, you can omit # this service and just `docker run myorg/etl:latest ...` on demand. # ─────────────────────────────────────────────────────────────────────────── etl: image: git.ivanch.me/ivanch/opencand.etl:latest container_name: opencand_etl restart: "no" environment: DatabaseSettings__ConnectionString: "Host=db;Port=5432;Database=opencand;Username=root;Password=root" ParserSettings_CandidatoCSVThreads: "40" BasePath: "etl-data" volumes: - ./etl-data:/app/etl-data logging: driver: "json-file" options: max-size: "10m" max-file: "3" labels: "service=etl" labels: - "promtail.enable=true" - "promtail.job=opencand-etl" db: image: postgres:14-alpine container_name: opencand_db profiles: ["infra"] restart: unless-stopped hostname: db shm_size: 4g environment: POSTGRES_USER: root POSTGRES_PASSWORD: root POSTGRES_DB: opencand volumes: - ./db-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U root -d opencand"] interval: 10s timeout: 5s retries: 5 logging: driver: "json-file" options: max-size: "10m" max-file: "3" labels: "service=database" labels: - "promtail.enable=true" - "promtail.job=opencand-db" # ─────────────────────────────────────────────────────────────────────────── # 5. Log Monitoring Stack # ─────────────────────────────────────────────────────────────────────────── # Loki - Log aggregation system loki: image: grafana/loki:2.9.0 container_name: opencand_loki profiles: ["infra"] restart: unless-stopped ports: - "127.0.0.1:6110:3100" command: -config.file=/etc/loki/local-config.yaml volumes: - ./monitoring/loki-config.yaml:/etc/loki/local-config.yaml - loki-data:/loki healthcheck: test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1"] interval: 10s timeout: 5s retries: 5 # Promtail - Log collection agent promtail: image: grafana/promtail:2.9.0 container_name: opencand_promtail profiles: ["infra"] restart: unless-stopped volumes: - ./monitoring/promtail-config.yaml:/etc/promtail/config.yml - /var/log:/var/log:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro - /var/run/docker.sock:/var/run/docker.sock:ro command: -config.file=/etc/promtail/config.yml depends_on: - loki # Prometheus - Metrics collection prometheus: image: prom/prometheus:v2.45.0 container_name: opencand_prometheus profiles: ["infra"] restart: unless-stopped ports: - "127.0.0.1:6090:9090" command: - "--config.file=/etc/prometheus/prometheus.yml" - "--storage.tsdb.path=/prometheus" - "--web.console.libraries=/etc/prometheus/console_libraries" - "--web.console.templates=/etc/prometheus/consoles" - "--web.enable-lifecycle" volumes: - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus depends_on: - node-exporter # Node Exporter - System metrics node-exporter: image: prom/node-exporter:v1.6.0 container_name: opencand_node_exporter profiles: ["infra"] restart: unless-stopped ports: - "127.0.0.1:6100:9100" volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - "--path.procfs=/host/proc" - "--path.rootfs=/rootfs" - "--path.sysfs=/host/sys" - "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)" # Grafana - Visualization and dashboards grafana: image: grafana/grafana:10.0.0 container_name: opencand_grafana profiles: ["infra"] restart: unless-stopped ports: - "6000:3000" environment: - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false volumes: - grafana-data:/var/lib/grafana - ./monitoring/grafana/provisioning:/etc/grafana/provisioning depends_on: - loki - prometheus volumes: loki-data: prometheus-data: grafana-data: