-
Notifications
You must be signed in to change notification settings - Fork 156
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
259 lines (249 loc) · 8.92 KB
/
Copy pathdocker-compose.yml
File metadata and controls
259 lines (249 loc) · 8.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
services:
redis:
image: redis:7-alpine
ports:
- "127.0.0.1:6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
postgres:
image: postgres:16-alpine
ports:
- "127.0.0.1:5432:5432"
environment:
POSTGRES_DB: nester_dev
POSTGRES_USER: nester
POSTGRES_PASSWORD: nester_dev_password
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U nester"]
interval: 5s
timeout: 5s
retries: 10
api:
build:
context: ./apps/api
dockerfile: Dockerfile.dev
ports:
- "127.0.0.1:8080:8080"
environment:
APP_ENV: development
DATABASE_DSN: postgres://nester:nester_dev_password@postgres:5432/nester_dev?sslmode=disable
REDIS_ADDR: redis:6379
STELLAR_NETWORK_PASSPHRASE: "Test SDF Network ; September 2015"
STELLAR_RPC_URL: https://soroban-testnet.stellar.org
STELLAR_HORIZON_URL: https://horizon-testnet.stellar.org
# Development JWT secret. Set via AUTH_JWT_SECRET env var or .env file.
# The development deny-list in internal/config/config.go accepts the default
# below, but production rejects it. If unset, falls back to the placeholder.
AUTH_JWT_SECRET: ${AUTH_JWT_SECRET:-dev-nester-jwt-secret-change-in-production}
LOG_LEVEL: info
LOG_FORMAT: text
RUN_MIGRATIONS: "true"
ALLOWED_ORIGINS: http://localhost:3001
# Tracing (nester#1054). Off unless TRACING_ENABLED is exported, so the
# default compose workflow is unchanged. The endpoint targets the
# collector over the compose network — localhost:4317 would resolve to
# this container, not the collector.
TRACING_ENABLED: ${TRACING_ENABLED:-false}
OTEL_EXPORTER_OTLP_ENDPOINT: otel-collector:4317
OTEL_EXPORTER_OTLP_INSECURE: "true"
# 1.0 because the collector applies tail sampling: a trace the head
# drops never reaches it. See deploy/observability/otel-collector.yaml.
TRACING_SAMPLE_RATIO: ${TRACING_SAMPLE_RATIO:-1.0}
# Bound to all interfaces inside the container so Prometheus can reach
# it over the compose network. Deliberately NOT published under `ports`
# below: the metrics endpoint stays reachable only from inside the
# compose network, never from the host's public interface.
METRICS_ADDR: 0.0.0.0:9090
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- ./apps/api:/app
- go_mod_cache:/go/pkg/mod
healthcheck:
# /healthz is the canonical liveness path (see README "Health
# endpoints"); /health remains a permanent alias for it. Liveness rather
# than /readyz on purpose: the services that wait on `service_healthy`
# need the process to be up, and readiness additionally fails on
# dependency outages this check should not restart the container for.
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/healthz || exit 1"]
interval: 10s
timeout: 5s
retries: 5
start_period: 15s
seed:
image: postgres:16-alpine
depends_on:
api:
condition: service_healthy
environment:
PGPASSWORD: nester_dev_password
volumes:
- ./scripts/seed.sql:/seed.sql:ro
command:
[
"psql",
"-h",
"postgres",
"-U",
"nester",
"-d",
"nester_dev",
"-v",
"ON_ERROR_STOP=1",
"-f",
"/seed.sql",
]
frontend:
build:
context: ./apps/dapp/frontend
dockerfile: Dockerfile.dev
ports:
- "127.0.0.1:3001:3001"
environment:
NEXT_PUBLIC_API_URL: http://localhost:8080/api/v1
NEXT_PUBLIC_WS_URL: ws://localhost:8080/ws
NEXT_PUBLIC_NETWORK: testnet
volumes:
- ./apps/dapp/frontend:/app
- /app/node_modules
- /app/.next
# --- Local observability: tracing (nester#1054) -----------------------
#
# Note for whoever merges second: PR #1065 (#1043, metrics) adds
# `prometheus` and `grafana` under this same profile. The two stacks are
# complementary and share no ports or volume names, so a conflict here is
# textual only — keep both blocks and both sets of volumes.
#
# Started only with an explicit profile:
# docker compose --profile observability up
#
# Both services are profile-gated, so a normal `docker compose up` is
# unchanged and tracing infrastructure is never a startup dependency for
# ordinary development.
#
# To send traces, run the app services with tracing switched on:
# TRACING_ENABLED=true # docker compose --profile observability up
#
# Then open the Jaeger UI at http://localhost:16686 and pick the
# "nester-api" service.
jaeger:
image: jaegertracing/all-in-one:1.62.0
profiles: ["observability"]
ports:
# Jaeger UI.
- "127.0.0.1:16686:16686"
environment:
# Jaeger accepts OTLP directly; the collector forwards to it here.
COLLECTOR_OTLP_ENABLED: "true"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:16686/"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
otel-collector:
image: otel/opentelemetry-collector-contrib:0.115.1
profiles: ["observability"]
command: ["--config=/etc/otel/config.yaml"]
volumes:
- ./deploy/observability/otel-collector.yaml:/etc/otel/config.yaml:ro
ports:
# OTLP gRPC — what both services export to by default.
- "127.0.0.1:4317:4317"
# OTLP HTTP, for tools that cannot speak gRPC.
- "127.0.0.1:4318:4318"
depends_on:
# Restored in nester#1056: the #1065/#1067 merge left this key with an
# empty body, which makes the whole compose file fail to parse — every
# `docker compose` command, not only the observability profile.
jaeger:
condition: service_healthy
# Local observability stack. Started only with:
# docker compose --profile observability up
# Services without a profile keep starting as before, so the default
# developer workflow is unchanged.
prometheus:
image: prom/prometheus:v3.1.0
profiles: ["observability"]
ports:
- "127.0.0.1:9091:9090"
volumes:
- ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
# SLO recording and alerting rules (nester#1056). Mounted read-only from
# the repo so the rules Prometheus loads locally are byte-identical to
# the ones CI validates with promtool.
- ./docker/prometheus/rules:/etc/prometheus/rules:ro
- prometheus_data:/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --storage.tsdb.retention.time=24h
# The local stack is for looking at graphs, not for storing history;
# 24h keeps the volume small.
depends_on:
api:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:9090/-/healthy"]
interval: 10s
timeout: 5s
retries: 5
# Alertmanager (nester#1056). Receives the burn-rate alerts and applies the
# routing and inhibition policy in docker/alertmanager/alertmanager.yml.
#
# Its receivers are deliberately empty: a local stack must not be able to
# page anyone. Alerts are still inspectable in the UI at
# http://localhost:9093, which is what makes the routing testable.
alertmanager:
image: prom/alertmanager:v0.28.0
profiles: ["observability"]
ports:
- "127.0.0.1:9093:9093"
volumes:
- ./docker/alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
- alertmanager_data:/alertmanager
command:
- --config.file=/etc/alertmanager/alertmanager.yml
- --storage.path=/alertmanager
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:9093/-/healthy"]
interval: 10s
timeout: 5s
retries: 5
grafana:
image: grafana/grafana:11.4.0
profiles: ["observability"]
ports:
- "127.0.0.1:3002:3000"
environment:
# Local-only convenience: anonymous viewer access so a developer does
# not have to log in to look at a graph. Never mirror this in a
# deployed environment.
GF_AUTH_ANONYMOUS_ENABLED: "true"
GF_AUTH_ANONYMOUS_ORG_ROLE: Admin
GF_SECURITY_ALLOW_EMBEDDING: "true"
volumes:
- ./docker/grafana/provisioning:/etc/grafana/provisioning:ro
# SLO dashboards (nester#1056), generated by
# scripts/build_slo_dashboards.py and committed. Every panel reads the
# recorded series the alerts fire on, so a dashboard cannot disagree
# with the pager during an incident.
- ./docker/grafana/dashboards:/etc/grafana/dashboards:ro
- grafana_data:/var/lib/grafana
depends_on:
prometheus:
condition: service_healthy
volumes:
postgres_data:
go_mod_cache:
prometheus_data:
alertmanager_data:
grafana_data: