docker-compose.yml 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # docker-compose.yml — single-host M0 stack.
  2. # Run: docker compose up -d
  3. # Then: see M0_VERIFICATION.md for the loadgen smoke test.
  4. #
  5. # Port conventions (project rule):
  6. # - app HTTP services: 8800–8899 (ingestd/routerd/deliverd/admind/loadgen)
  7. # - canonical ports stay (5432 postgres, 4222 nats, 6379 redis,
  8. # 1883 mqtt, 9090 prometheus, 3000 grafana, etc.)
  9. services:
  10. # ── Data tier ────────────────────────────────────────────────────
  11. postgres:
  12. image: timescale/timescaledb:latest-pg16
  13. environment:
  14. POSTGRES_USER: ba
  15. POSTGRES_PASSWORD: ba
  16. POSTGRES_DB: ba
  17. ports: ["5432:5432"]
  18. volumes:
  19. - pgdata:/var/lib/postgresql/data
  20. healthcheck:
  21. test: ["CMD-SHELL", "pg_isready -U ba"]
  22. interval: 5s
  23. timeout: 3s
  24. retries: 10
  25. redis:
  26. image: redis:7-alpine
  27. ports: ["6379:6379"]
  28. healthcheck:
  29. test: ["CMD", "redis-cli", "ping"]
  30. interval: 5s
  31. timeout: 3s
  32. retries: 10
  33. nats:
  34. image: nats:2.10-alpine
  35. command: ["-js", "-sd", "/data"]
  36. ports: ["4222:4222", "8222:8222"] # 8222 is the monitoring HTTP
  37. volumes:
  38. - natsdata:/data
  39. healthcheck:
  40. test: ["CMD", "wget", "-qO-", "http://localhost:8222/healthz"]
  41. interval: 5s
  42. timeout: 3s
  43. retries: 10
  44. emqx:
  45. image: emqx/emqx:5-alpine
  46. ports: ["1883:1883", "18083:18083"] # MQTT + admin UI
  47. healthcheck:
  48. test: ["CMD", "/opt/emqx/bin/emqx", "ping"]
  49. interval: 10s
  50. timeout: 5s
  51. retries: 10
  52. clickhouse:
  53. image: clickhouse/clickhouse-server:24-alpine
  54. ports: ["8123:8123", "9000:9000"]
  55. volumes:
  56. - chdata:/var/lib/clickhouse
  57. ulimits:
  58. nofile: { soft: 262144, hard: 262144 }
  59. # ── App tier ─────────────────────────────────────────────────────
  60. ingestd:
  61. build: .
  62. command: ["/app/ingestd"]
  63. environment:
  64. BA_ENV: dev
  65. BA_HTTP_ADDR: ":8800"
  66. BA_NATS_URL: nats://nats:4222
  67. BA_REDIS_URL: redis://redis:6379/0
  68. BA_POSTGRES_DSN: postgres://ba:ba@postgres:5432/ba?sslmode=disable
  69. BA_INGESTD_SOURCES: "acme-001:prom-prod:s3cret-acme,globex-002:grafana:s3cret-globex"
  70. BA_INGESTD_RATE_LIMIT_PER_SOURCE: "100"
  71. BA_INGESTD_RATE_LIMIT_PER_COMPANY: "10000"
  72. ports: ["8800:8800"]
  73. depends_on:
  74. nats: { condition: service_healthy }
  75. redis: { condition: service_healthy }
  76. postgres: { condition: service_healthy }
  77. routerd:
  78. build: .
  79. command: ["/app/routerd"]
  80. environment:
  81. BA_ENV: dev
  82. BA_HTTP_ADDR: ":8801"
  83. BA_NATS_URL: nats://nats:4222
  84. BA_POSTGRES_DSN: postgres://ba:ba@postgres:5432/ba?sslmode=disable
  85. ports: ["8801:8801"]
  86. depends_on:
  87. nats: { condition: service_healthy }
  88. postgres: { condition: service_healthy }
  89. deliverd:
  90. build: .
  91. command: ["/app/deliverd"]
  92. environment:
  93. BA_ENV: dev
  94. BA_HTTP_ADDR: ":8802"
  95. BA_NATS_URL: nats://nats:4222
  96. BA_POSTGRES_DSN: postgres://ba:ba@postgres:5432/ba?sslmode=disable
  97. BA_FAKECMD_URL: "http://fakefcmd:8820"
  98. ports: ["8802:8802"]
  99. depends_on:
  100. nats: { condition: service_healthy }
  101. postgres: { condition: service_healthy }
  102. fakefcmd: { condition: service_started }
  103. fakefcmd:
  104. build: .
  105. command: ["/app/fakefcmd", "--addr", ":8820"]
  106. ports: ["8820:8820"]
  107. healthcheck:
  108. test: ["CMD", "wget", "-qO-", "http://localhost:8820/health"]
  109. interval: 5s
  110. timeout: 3s
  111. retries: 10
  112. seed:
  113. build: .
  114. command: ["/app/seed"]
  115. environment:
  116. BA_POSTGRES_DSN: postgres://ba:ba@postgres:5432/ba?sslmode=disable
  117. BA_MIGRATIONS_DIR: /migrations
  118. volumes:
  119. - ./migrations:/migrations:ro
  120. depends_on:
  121. postgres: { condition: service_healthy }
  122. admind:
  123. build: .
  124. command: ["/app/admind"]
  125. environment:
  126. BA_ENV: dev
  127. BA_HTTP_ADDR: ":8803"
  128. BA_NATS_URL: nats://nats:4222
  129. BA_POSTGRES_DSN: postgres://ba:ba@postgres:5432/ba?sslmode=disable
  130. ports: ["8803:8803"]
  131. depends_on:
  132. nats: { condition: service_healthy }
  133. postgres: { condition: service_healthy }
  134. # ── Observability ────────────────────────────────────────────────
  135. prometheus:
  136. image: prom/prometheus:latest
  137. command:
  138. - --config.file=/etc/prometheus/prometheus.yml
  139. volumes:
  140. - ./deploy/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
  141. ports: ["9090:9090"]
  142. depends_on: [ingestd, routerd, deliverd, admind]
  143. grafana:
  144. image: grafana/grafana:latest
  145. ports: ["3000:3000"]
  146. environment:
  147. GF_SECURITY_ADMIN_USER: admin
  148. GF_SECURITY_ADMIN_PASSWORD: admin
  149. depends_on: [prometheus]
  150. # ── Loadgen (one-shot smoke profile) ────────────────────
  151. loadgen-http:
  152. build: .
  153. command:
  154. - /app/loadgen-http
  155. - --target=http://ingestd:8800
  156. - --api-key=acme-001:prom-prod:s3cret-acme
  157. - --mode=normal
  158. - --rate=50
  159. - --duration=30s
  160. - --metrics=:8891
  161. profiles: ["loadgen"]
  162. depends_on:
  163. ingestd: { condition: service_started }
  164. volumes:
  165. pgdata: {}
  166. natsdata: {}
  167. chdata: {}