compose.yml 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. # Observability stack — Grafana + Loki + Prometheus + Promtail.
  2. #
  3. # Single Dokploy compose project. Sits on the same docker network as
  4. # apps/api, apps/runtime, apps/realtime so Prometheus can scrape their
  5. # /metrics endpoints by container name. Grafana is exposed via Traefik
  6. # behind Cloudflare Access; the rest are internal-only.
  7. #
  8. # Per DOCKER.md (project root):
  9. # - Promtail uses file-based discovery against /var/lib/docker/containers
  10. # (read-only). NO docker.sock mount. NO docker_sd_configs.
  11. # - Prometheus uses static_configs against service DNS names. NO
  12. # docker_sd_configs. NO scraping of unix:///var/run/docker.sock.
  13. # - Every service has logging.options.max-size set (rule §7).
  14. #
  15. # See ./README.md for the operator runbook.
  16. x-logging: &briven-logging
  17. driver: json-file
  18. options:
  19. max-size: '10m'
  20. max-file: '3'
  21. services:
  22. prometheus:
  23. image: prom/prometheus:v3.0.1
  24. restart: unless-stopped
  25. logging: *briven-logging
  26. command:
  27. - '--config.file=/etc/prometheus/prometheus.yml'
  28. - '--storage.tsdb.path=/prometheus'
  29. - '--storage.tsdb.retention.time=30d'
  30. - '--web.enable-lifecycle'
  31. volumes:
  32. - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
  33. - ./prometheus/rules:/etc/prometheus/rules:ro
  34. - prometheus_data:/prometheus
  35. depends_on:
  36. - alertmanager
  37. networks:
  38. - dokploy-network
  39. alertmanager:
  40. image: prom/alertmanager:v0.27.0
  41. restart: unless-stopped
  42. logging: *briven-logging
  43. command:
  44. - '--config.file=/etc/alertmanager/alertmanager.yml'
  45. - '--storage.path=/alertmanager'
  46. volumes:
  47. - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
  48. - alertmanager_data:/alertmanager
  49. networks:
  50. - dokploy-network
  51. # Translator sidecar — alertmanager webhook → discord webhook payload.
  52. # Two instances, one per channel, each holding a different webhook url.
  53. # The url is held inside the container's env so it never lands in the
  54. # repo. J sets BRIVEN_DISCORD_WEBHOOK_ALERTS + BRIVEN_DISCORD_WEBHOOK_DEPLOYS
  55. # in the dokploy project's environment per CLAUDE.md §4.1 (BRIVEN_ prefix
  56. # on every briven-owned env var) and docs/runbooks/discord-setup.md §4.
  57. alertmanager-discord-alerts:
  58. image: benjojo/alertmanager-discord:latest
  59. restart: unless-stopped
  60. logging: *briven-logging
  61. environment:
  62. DISCORD_WEBHOOK: ${BRIVEN_DISCORD_WEBHOOK_ALERTS}
  63. LISTEN_ADDRESS: ':9094'
  64. networks:
  65. - dokploy-network
  66. alertmanager-discord-deploys:
  67. image: benjojo/alertmanager-discord:latest
  68. restart: unless-stopped
  69. logging: *briven-logging
  70. environment:
  71. DISCORD_WEBHOOK: ${BRIVEN_DISCORD_WEBHOOK_DEPLOYS}
  72. LISTEN_ADDRESS: ':9094'
  73. networks:
  74. - dokploy-network
  75. loki:
  76. image: grafana/loki:3.3.2
  77. restart: unless-stopped
  78. logging: *briven-logging
  79. command: -config.file=/etc/loki/config.yaml
  80. volumes:
  81. - ./loki/config.yaml:/etc/loki/config.yaml:ro
  82. - loki_data:/loki
  83. networks:
  84. - dokploy-network
  85. # Promtail — file-based docker log discovery per DOCKER.md §1. The
  86. # /var/lib/docker/containers bind-mount is read-only so Promtail can
  87. # tail the json-file driver's output without touching the daemon.
  88. # DO NOT bind-mount /var/run/docker.sock here (rule §6). DO NOT switch
  89. # to docker_sd_configs (rule §1).
  90. promtail:
  91. image: grafana/promtail:3.3.2
  92. restart: unless-stopped
  93. logging: *briven-logging
  94. command: -config.file=/etc/promtail/config.yaml
  95. volumes:
  96. - ./promtail/config.yaml:/etc/promtail/config.yaml:ro
  97. - /var/lib/docker/containers:/var/lib/docker/containers:ro
  98. depends_on:
  99. - loki
  100. networks:
  101. - dokploy-network
  102. # Host metrics — CPU (incl. steal), memory, swap, load, disk/filesystem.
  103. # Unprivileged; read-only host mounts; NO docker.sock (DOCKER.md §6).
  104. node-exporter:
  105. image: prom/node-exporter:v1.8.2
  106. restart: unless-stopped
  107. logging: *briven-logging
  108. command:
  109. - '--path.rootfs=/host'
  110. - '--path.procfs=/host/proc'
  111. - '--path.sysfs=/host/sys'
  112. - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
  113. pid: host
  114. volumes:
  115. - /:/host:ro,rslave
  116. networks:
  117. - dokploy-network
  118. # Per-container CPU/memory — catches a runaway build before it swap-kills
  119. # the host. Reads cgroupfs + /var/lib/docker (read-only) for container
  120. # names; NO docker.sock mount, NO /var/run (DOCKER.md §6). If container
  121. # metrics don't appear on some kernels, add `privileged: true`.
  122. cadvisor:
  123. image: gcr.io/cadvisor/cadvisor:v0.49.1
  124. restart: unless-stopped
  125. logging: *briven-logging
  126. command:
  127. - '--docker_only=false'
  128. - '--housekeeping_interval=30s'
  129. - '--store_container_labels=false'
  130. devices:
  131. - /dev/kmsg
  132. volumes:
  133. - /:/rootfs:ro
  134. - /sys:/sys:ro
  135. - /var/lib/docker/:/var/lib/docker:ro
  136. - /dev/disk/:/dev/disk:ro
  137. networks:
  138. - dokploy-network
  139. grafana:
  140. image: grafana/grafana:11.4.0
  141. restart: unless-stopped
  142. logging: *briven-logging
  143. environment:
  144. # Local-auth mode — operator signs in with the bootstrap admin
  145. # password set via env. Promotable to cf-access proxy auth later
  146. # by overriding GF_AUTH_PROXY_ENABLED=true and the header vars.
  147. GF_SECURITY_ADMIN_USER: ${GRAFANA_ADMIN_USER:-admin}
  148. GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD}
  149. GF_USERS_ALLOW_SIGN_UP: 'false'
  150. GF_SECURITY_ALLOW_EMBEDDING: 'false'
  151. GF_ANALYTICS_REPORTING_ENABLED: 'false'
  152. GF_ANALYTICS_CHECK_FOR_UPDATES: 'false'
  153. volumes:
  154. - ./grafana/grafana.ini:/etc/grafana/grafana.ini:ro
  155. - ./grafana/provisioning:/etc/grafana/provisioning:ro
  156. - ./grafana/dashboards:/var/lib/grafana/dashboards:ro
  157. - grafana_data:/var/lib/grafana
  158. depends_on:
  159. - prometheus
  160. - loki
  161. networks:
  162. - dokploy-network
  163. labels:
  164. - 'traefik.enable=true'
  165. - 'traefik.docker.network=dokploy-network'
  166. - 'traefik.http.routers.briven-grafana.rule=Host(`grafana.briven.tech`)'
  167. - 'traefik.http.routers.briven-grafana.entrypoints=websecure'
  168. - 'traefik.http.routers.briven-grafana.tls.certresolver=letsencrypt'
  169. - 'traefik.http.services.briven-grafana.loadbalancer.server.port=3000'
  170. volumes:
  171. prometheus_data:
  172. alertmanager_data:
  173. loki_data:
  174. grafana_data:
  175. networks:
  176. dokploy-network:
  177. external: true