@toon-protocol/hub 0.34.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,415 @@
1
+ # Townhouse Dev Stack — Docker Compose (Story 21.8.0, D21-009)
2
+ #
3
+ # Full contributor dev topology: 1 standalone connector + 2 Town + 2 Mill + 1 DVM
4
+ # + 3 chain devnets + 1 SOCKS5 proxy.
5
+ #
6
+ # This file is intentionally separate from docker-compose-townhouse.yml.
7
+ # Production describes one operator's actual node. This file describes a
8
+ # contributor's rig with enough instances to exercise every dashboard view.
9
+ # See story 21.8.0 Dev Notes for the full rationale.
10
+ #
11
+ # Canonical path (npm tarball): packages/townhouse/compose/townhouse-dev.yml
12
+ # Ships verbatim inside @toon-protocol/hub dist/compose/townhouse-dev.yml
13
+ # (Story 45.2 — no digest substitution; uses local toon:* image tags).
14
+ #
15
+ # Legacy path (backward-compat): docker-compose-townhouse-dev.yml (repo root)
16
+ # Used by scripts/townhouse-dev-infra.sh and existing CI. Preserved until
17
+ # a follow-up story routes the script through the package-local copy.
18
+ #
19
+ # Usage:
20
+ # ./scripts/townhouse-dev-infra.sh up # Build, start, wait for health (reads root path)
21
+ # ./scripts/townhouse-dev-infra.sh down # Stop containers, remove .env.townhouse-dev
22
+ # ./scripts/townhouse-dev-infra.sh down-v # Same + remove volumes
23
+ # ./scripts/townhouse-dev-infra.sh status # Show container state
24
+ #
25
+ # Port allocation — 28xxx range (no collision with SDK E2E 18xxx/19xxx or
26
+ # production Townhouse 3xxx/7100/9401). See CLAUDE.md "Townhouse Dev Stack (28xxx)".
27
+ #
28
+ # All host bindings use 127.0.0.1 — never 0.0.0.0 (developer machine).
29
+ #
30
+ # Connector image tag must match DEFAULT_CONNECTOR_IMAGE in
31
+ # packages/townhouse/src/constants.ts — keep both in sync when bumping.
32
+
33
+ networks:
34
+ townhouse-dev-net:
35
+ driver: bridge
36
+
37
+ volumes:
38
+ townhouse-dev-connector-data:
39
+ townhouse-dev-town-01-data:
40
+ townhouse-dev-town-02-data:
41
+ townhouse-dev-mill-01-data:
42
+ townhouse-dev-mill-02-data:
43
+ townhouse-dev-dvm-01-data:
44
+
45
+ services:
46
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
47
+ # Connector — standalone connector for all 5 child peers
48
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
49
+ townhouse-dev-connector:
50
+ # Image tag must match DEFAULT_CONNECTOR_IMAGE in packages/townhouse/src/constants.ts
51
+ image: ghcr.io/toon-protocol/connector:3.10.0
52
+ container_name: townhouse-dev-connector
53
+ networks:
54
+ - townhouse-dev-net
55
+ ports:
56
+ - '127.0.0.1:28080:9401'
57
+ environment:
58
+ CONFIG_FILE: /config/connector.yaml
59
+ volumes:
60
+ - ./docker/configs/townhouse-dev-connector.yaml:/config/connector.yaml:ro
61
+ - townhouse-dev-connector-data:/data
62
+ restart: unless-stopped
63
+ healthcheck:
64
+ # nosemgrep: trailofbits.generic.wget-unencrypted-url.wget-unencrypted-url -- container-internal health probe
65
+ test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:9401/health']
66
+ interval: 10s
67
+ timeout: 5s
68
+ retries: 5
69
+ start_period: 15s
70
+
71
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
72
+ # Anvil — Local Ethereum (chain-id 31337) with auto-deployed contracts
73
+ # Copied from docker-compose-sdk-e2e.yml, ports shifted to 28xxx range
74
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
75
+ townhouse-dev-anvil:
76
+ image: ghcr.io/foundry-rs/foundry:latest
77
+ container_name: townhouse-dev-anvil
78
+ entrypoint: []
79
+ command:
80
+ - sh
81
+ - -c
82
+ - |
83
+ echo "Starting Anvil..."
84
+ anvil --host 0.0.0.0 --port 8545 --chain-id 31337 --accounts 10 --balance 10000 &
85
+ ANVIL_PID=$$!
86
+
87
+ echo "Waiting for Anvil to be ready..."
88
+ until cast client --rpc-url http://localhost:8545 2>/dev/null | grep -q 'anvil'; do
89
+ sleep 1
90
+ done
91
+
92
+ echo "Deploying contracts..."
93
+ cd /contracts
94
+ forge script script/DeployLocal.s.sol:DeployLocalScript --rpc-url http://localhost:8545 --broadcast --skip-simulation || echo "Deployment failed (non-fatal)"
95
+
96
+ echo "Funding test accounts with Mock USDC..."
97
+ DEPLOYER_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
98
+ TOKEN=0x5FbDB2315678afecb367f032d93F642f64180aa3
99
+ AMOUNT=10000000000000000000000
100
+ for ADDR in \
101
+ 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 \
102
+ 0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 \
103
+ 0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc \
104
+ 0x976EA74026E726554dB657fA54763abd0C3a0aa9 \
105
+ 0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 \
106
+ 0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f \
107
+ 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720; do
108
+ cast send --rpc-url http://localhost:8545 --private-key $$DEPLOYER_KEY \
109
+ $$TOKEN "transfer(address,uint256)" $$ADDR $$AMOUNT 2>/dev/null \
110
+ && echo "Funded $$ADDR" || echo "Fund $$ADDR failed (non-fatal)"
111
+ done
112
+
113
+ echo "Anvil ready with contracts deployed!"
114
+ wait $$ANVIL_PID
115
+ volumes:
116
+ - ./contracts/evm:/contracts
117
+ ports:
118
+ - '127.0.0.1:28545:8545'
119
+ networks:
120
+ - townhouse-dev-net
121
+ restart: unless-stopped
122
+ healthcheck:
123
+ test:
124
+ [
125
+ 'CMD-SHELL',
126
+ "cast client --rpc-url http://localhost:8545 2>&1 | grep -q 'anvil' || exit 1",
127
+ ]
128
+ interval: 10s
129
+ timeout: 5s
130
+ retries: 3
131
+ start_period: 15s
132
+
133
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
134
+ # Solana Test Validator — ports shifted to 28xxx range
135
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
136
+ townhouse-dev-solana:
137
+ image: ghcr.io/beeman/solana-test-validator:latest
138
+ container_name: townhouse-dev-solana
139
+ entrypoint: []
140
+ command:
141
+ - sh
142
+ - /entrypoint.sh
143
+ volumes:
144
+ - ./infra/solana/entrypoint.sh:/entrypoint.sh:ro
145
+ - ./contracts/solana:/programs:ro
146
+ tmpfs:
147
+ - /tmp/test-ledger
148
+ ports:
149
+ - '127.0.0.1:28899:8899' # RPC
150
+ - '127.0.0.1:28900:8900' # WebSocket
151
+ networks:
152
+ - townhouse-dev-net
153
+ security_opt:
154
+ - seccomp=unconfined
155
+ restart: unless-stopped
156
+ healthcheck:
157
+ test: ['CMD-SHELL', 'solana cluster-version --url http://localhost:8899 >/dev/null 2>&1']
158
+ interval: 5s
159
+ timeout: 5s
160
+ retries: 12
161
+ start_period: 10s
162
+
163
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
164
+ # Mina Lightnet — ports shifted to 28xxx range
165
+ # NOTE: Requires 4-8 GB RAM (see SDK E2E notes)
166
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
167
+ townhouse-dev-mina:
168
+ image: o1labs/mina-local-network:compatible-latest-lightnet
169
+ container_name: townhouse-dev-mina
170
+ environment:
171
+ NETWORK_TYPE: single-node
172
+ PROOF_LEVEL: none
173
+ LOG_LEVEL: Info
174
+ RUN_ARCHIVE_NODE: 'false'
175
+ SLOT_TIME: '20000'
176
+ ports:
177
+ - '127.0.0.1:28085:3085' # GraphQL (direct to daemon)
178
+ - '127.0.0.1:28181:8181' # Accounts Manager
179
+ networks:
180
+ - townhouse-dev-net
181
+ deploy:
182
+ resources:
183
+ limits:
184
+ memory: 4g
185
+ restart: unless-stopped
186
+ healthcheck:
187
+ test:
188
+ [
189
+ 'CMD-SHELL',
190
+ 'curl -sf -X POST -H "Content-Type: application/json" -d "{\"query\":\"{syncStatus}\"}" http://localhost:3085/graphql | grep -q SYNCED || exit 1',
191
+ ]
192
+ interval: 10s
193
+ timeout: 10s
194
+ retries: 30
195
+ start_period: 180s
196
+
197
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
198
+ # SOCKS5 Proxy — optional; required for ATOR transport testing (story 21.15)
199
+ # Connector defaults to TRANSPORT_MODE: direct; proxy only needed for ATOR mode.
200
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
201
+ townhouse-dev-socks5:
202
+ image: serjs/go-socks5-proxy:latest
203
+ container_name: townhouse-dev-socks5
204
+ ports:
205
+ - '127.0.0.1:28050:1080'
206
+ networks:
207
+ - townhouse-dev-net
208
+ restart: unless-stopped
209
+
210
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
211
+ # Town 01 — Nostr relay node (instance 1 of 2)
212
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
213
+ townhouse-dev-town-01:
214
+ image: toon:town
215
+ container_name: townhouse-dev-town-01
216
+ networks:
217
+ - townhouse-dev-net
218
+ depends_on:
219
+ townhouse-dev-connector:
220
+ condition: service_healthy
221
+ expose:
222
+ - '3000'
223
+ ports:
224
+ - '127.0.0.1:28100:3100' # BLS health
225
+ - '127.0.0.1:28700:7100' # Nostr relay WebSocket
226
+ environment:
227
+ # nosemgrep: detect-insecure-websocket -- Docker-internal, TLS unnecessary
228
+ CONNECTOR_URL: ws://townhouse-dev-connector:3000
229
+ CONNECTOR_ADMIN_URL: http://townhouse-dev-connector:9401
230
+ FEE_PER_EVENT: '0'
231
+ # NIP-40 TTL (seconds) for the kind:10032 announcement + heartbeat (#261).
232
+ TOON_ANNOUNCEMENT_TTL_SECONDS: ${TOON_ANNOUNCEMENT_TTL_SECONDS:-3600}
233
+ # Interpolated from TOWN_01_NOSTR_PUBKEY exported by townhouse-dev-infra.sh (issue #81).
234
+ NODE_NOSTR_PUBKEY: '${TOWN_01_NOSTR_PUBKEY:-}'
235
+ NODE_EVM_ADDRESS: ''
236
+ # Interpolated from TOWN_01_SECRET_KEY exported by townhouse-dev-infra.sh.
237
+ NODE_NOSTR_SECRET_KEY: '${TOWN_01_SECRET_KEY:?TOWN_01_SECRET_KEY required — source scripts/townhouse-dev-infra.sh first}'
238
+ volumes:
239
+ - townhouse-dev-town-01-data:/data
240
+ healthcheck:
241
+ # nosemgrep: trailofbits.generic.wget-unencrypted-url.wget-unencrypted-url -- container-internal health probe
242
+ test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:3100/health']
243
+ interval: 30s
244
+ timeout: 10s
245
+ retries: 3
246
+ start_period: 5s
247
+ restart: unless-stopped
248
+
249
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
250
+ # Town 02 — Nostr relay node (instance 2 of 2)
251
+ # Story 21.10 exercises degraded state via `docker pause townhouse-dev-town-02`
252
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
253
+ townhouse-dev-town-02:
254
+ image: toon:town
255
+ container_name: townhouse-dev-town-02
256
+ networks:
257
+ - townhouse-dev-net
258
+ depends_on:
259
+ townhouse-dev-connector:
260
+ condition: service_healthy
261
+ expose:
262
+ - '3000'
263
+ ports:
264
+ - '127.0.0.1:28110:3100' # BLS health
265
+ - '127.0.0.1:28710:7100' # Nostr relay WebSocket
266
+ environment:
267
+ # nosemgrep: detect-insecure-websocket -- Docker-internal, TLS unnecessary
268
+ CONNECTOR_URL: ws://townhouse-dev-connector:3000
269
+ CONNECTOR_ADMIN_URL: http://townhouse-dev-connector:9401
270
+ FEE_PER_EVENT: '0'
271
+ # NIP-40 TTL (seconds) for the kind:10032 announcement + heartbeat (#261).
272
+ TOON_ANNOUNCEMENT_TTL_SECONDS: ${TOON_ANNOUNCEMENT_TTL_SECONDS:-3600}
273
+ # Interpolated from TOWN_02_NOSTR_PUBKEY exported by townhouse-dev-infra.sh (issue #81).
274
+ NODE_NOSTR_PUBKEY: '${TOWN_02_NOSTR_PUBKEY:-}'
275
+ NODE_EVM_ADDRESS: ''
276
+ # Interpolated from TOWN_02_SECRET_KEY exported by townhouse-dev-infra.sh.
277
+ NODE_NOSTR_SECRET_KEY: '${TOWN_02_SECRET_KEY:?TOWN_02_SECRET_KEY required — source scripts/townhouse-dev-infra.sh first}'
278
+ volumes:
279
+ - townhouse-dev-town-02-data:/data
280
+ healthcheck:
281
+ # nosemgrep: trailofbits.generic.wget-unencrypted-url.wget-unencrypted-url -- container-internal health probe
282
+ test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:3100/health']
283
+ interval: 30s
284
+ timeout: 10s
285
+ retries: 3
286
+ start_period: 5s
287
+ restart: unless-stopped
288
+
289
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
290
+ # Mill 01 — EVM↔Solana swap peer (story 21.11 AC names this exact container)
291
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
292
+ townhouse-dev-mill-01:
293
+ image: toon:mill
294
+ container_name: townhouse-dev-mill-01
295
+ networks:
296
+ - townhouse-dev-net
297
+ depends_on:
298
+ townhouse-dev-connector:
299
+ condition: service_healthy
300
+ townhouse-dev-anvil:
301
+ condition: service_healthy
302
+ townhouse-dev-solana:
303
+ condition: service_healthy
304
+ expose:
305
+ - '3000'
306
+ ports:
307
+ - '127.0.0.1:28200:3200' # BLS health
308
+ environment:
309
+ # nosemgrep: detect-insecure-websocket -- Docker-internal, TLS unnecessary
310
+ CONNECTOR_URL: ws://townhouse-dev-connector:3000
311
+ FEE_BASIS_POINTS: '0'
312
+ # Interpolated from MILL_01_NOSTR_PUBKEY exported by townhouse-dev-infra.sh (issue #81).
313
+ NODE_NOSTR_PUBKEY: '${MILL_01_NOSTR_PUBKEY:-}'
314
+ NODE_EVM_ADDRESS: ''
315
+ # MILL_MNEMONIC takes priority over NODE_NOSTR_SECRET_KEY for BIP-32 swap key derivation.
316
+ # Interpolated from MILL_01_MNEMONIC exported by townhouse-dev-infra.sh.
317
+ MILL_MNEMONIC: '${MILL_01_MNEMONIC:?MILL_01_MNEMONIC required — source scripts/townhouse-dev-infra.sh first}'
318
+ # Kept for backward-compat; ignored when MILL_MNEMONIC is set.
319
+ NODE_NOSTR_SECRET_KEY: '${MILL_01_SECRET_KEY:?MILL_01_SECRET_KEY required — source scripts/townhouse-dev-infra.sh first}'
320
+ MILL_CONFIG_PATH: /config/mill.config.json
321
+ MILL_RELAYS: ws://townhouse-dev-town-01:7100,ws://townhouse-dev-town-02:7100
322
+ volumes:
323
+ - ./docker/dev-fixtures/mill-01.config.json:/config/mill.config.json:ro
324
+ - townhouse-dev-mill-01-data:/data
325
+ healthcheck:
326
+ # nosemgrep: trailofbits.generic.wget-unencrypted-url.wget-unencrypted-url -- container-internal health probe
327
+ test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:3200/health']
328
+ interval: 30s
329
+ timeout: 10s
330
+ retries: 3
331
+ start_period: 5s
332
+ restart: unless-stopped
333
+
334
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
335
+ # Mill 02 — EVM↔Mina swap peer (story 21.11 AC names this exact container)
336
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
337
+ townhouse-dev-mill-02:
338
+ image: toon:mill
339
+ container_name: townhouse-dev-mill-02
340
+ networks:
341
+ - townhouse-dev-net
342
+ depends_on:
343
+ townhouse-dev-connector:
344
+ condition: service_healthy
345
+ townhouse-dev-anvil:
346
+ condition: service_healthy
347
+ townhouse-dev-mina:
348
+ condition: service_healthy
349
+ expose:
350
+ - '3000'
351
+ ports:
352
+ - '127.0.0.1:28210:3200' # BLS health
353
+ environment:
354
+ # nosemgrep: detect-insecure-websocket -- Docker-internal, TLS unnecessary
355
+ CONNECTOR_URL: ws://townhouse-dev-connector:3000
356
+ FEE_BASIS_POINTS: '0'
357
+ # Interpolated from MILL_02_NOSTR_PUBKEY exported by townhouse-dev-infra.sh (issue #81).
358
+ NODE_NOSTR_PUBKEY: '${MILL_02_NOSTR_PUBKEY:-}'
359
+ NODE_EVM_ADDRESS: ''
360
+ # MILL_MNEMONIC takes priority over NODE_NOSTR_SECRET_KEY for BIP-32 swap key derivation.
361
+ # Interpolated from MILL_02_MNEMONIC exported by townhouse-dev-infra.sh.
362
+ MILL_MNEMONIC: '${MILL_02_MNEMONIC:?MILL_02_MNEMONIC required — source scripts/townhouse-dev-infra.sh first}'
363
+ # Kept for backward-compat; ignored when MILL_MNEMONIC is set.
364
+ NODE_NOSTR_SECRET_KEY: '${MILL_02_SECRET_KEY:?MILL_02_SECRET_KEY required — source scripts/townhouse-dev-infra.sh first}'
365
+ MILL_CONFIG_PATH: /config/mill.config.json
366
+ MILL_RELAYS: ws://townhouse-dev-town-01:7100,ws://townhouse-dev-town-02:7100
367
+ volumes:
368
+ - ./docker/dev-fixtures/mill-02.config.json:/config/mill.config.json:ro
369
+ - townhouse-dev-mill-02-data:/data
370
+ healthcheck:
371
+ # nosemgrep: trailofbits.generic.wget-unencrypted-url.wget-unencrypted-url -- container-internal health probe
372
+ test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:3200/health']
373
+ interval: 30s
374
+ timeout: 10s
375
+ retries: 3
376
+ start_period: 5s
377
+ restart: unless-stopped
378
+
379
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
380
+ # DVM 01 — data vending machine (story 21.12 AC names this exact container)
381
+ # TURBO_TOKEN: pass through from host env; absence is non-fatal (disabled-upload mode)
382
+ # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
383
+ townhouse-dev-dvm-01:
384
+ image: toon:dvm
385
+ container_name: townhouse-dev-dvm-01
386
+ networks:
387
+ - townhouse-dev-net
388
+ depends_on:
389
+ townhouse-dev-connector:
390
+ condition: service_healthy
391
+ expose:
392
+ - '3300'
393
+ ports:
394
+ - '127.0.0.1:28400:3400' # BLS health
395
+ environment:
396
+ # nosemgrep: detect-insecure-websocket -- Docker-internal, TLS unnecessary
397
+ CONNECTOR_URL: ws://townhouse-dev-connector:3000
398
+ FEE_PER_JOB: '0'
399
+ # Interpolated from DVM_01_NOSTR_PUBKEY exported by townhouse-dev-infra.sh (issue #81).
400
+ NODE_NOSTR_PUBKEY: '${DVM_01_NOSTR_PUBKEY:-}'
401
+ NODE_EVM_ADDRESS: ''
402
+ # Interpolated from DVM_01_SECRET_KEY exported by townhouse-dev-infra.sh.
403
+ NODE_NOSTR_SECRET_KEY: '${DVM_01_SECRET_KEY:?DVM_01_SECRET_KEY required — source scripts/townhouse-dev-infra.sh first}'
404
+ # TURBO_TOKEN may legitimately be unset for non-Turbo dev paths — empty string is intended.
405
+ TURBO_TOKEN: '${TURBO_TOKEN:-}'
406
+ volumes:
407
+ - townhouse-dev-dvm-01-data:/data
408
+ healthcheck:
409
+ # nosemgrep: trailofbits.generic.wget-unencrypted-url.wget-unencrypted-url -- container-internal health probe
410
+ test: ['CMD', 'wget', '-q', '--spider', 'http://localhost:3400/health']
411
+ interval: 30s
412
+ timeout: 10s
413
+ retries: 3
414
+ start_period: 5s
415
+ restart: unless-stopped