Repository navigation
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
132 lines (126 loc) · 5.47 KB
/
Copy pathdocker-compose.yml
File metadata and controls
132 lines (126 loc) · 5.47 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
# Nuron infra stack -- Postgres, Neo4j, RustFS (NU-001).
#
# nuron-web / nuron-api / nuron-ai are not scaffolded here: there is no application code
# for them yet (later stories build those containers). This file stands up the three
# stateful backends everything else depends on.
#
# Per docs/tracer-bullet-01.md's architecture table, all three are internal-only -- no
# host port is published by default. Reach them with `docker compose exec` (psql /
# cypher-shell) during development; uncomment a `ports:` block below only for local
# debugging with a GUI client.
#
# Dev runtime is OrbStack. It's a drop-in Docker-compatible engine, so nothing here is
# OrbStack-specific.
services:
postgres:
image: postgres:18-alpine
# unless-stopped restarts on process exit, not on healthcheck failure. If
# schema.sql dies on first boot, PGDATA already exists, so the next start
# skips init scripts and stays up — unhealthy because the schema-complete
# marker is missing. That is the tripwire, not a restart loop. Re-apply without wiping:
# docker compose exec postgres sh -c 'psql -v ON_ERROR_STOP=1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" \
# -f /docker-entrypoint-initdb.d/01-schema.sql'
# Clean retry wipes postgres, neo4j, AND rustfs volumes:
# docker compose down -v && docker compose up -d
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:?POSTGRES_USER is required}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
POSTGRES_DB: ${POSTGRES_DB:?POSTGRES_DB is required}
NURON_AI_DB_PASSWORD: ${NURON_AI_DB_PASSWORD:?NURON_AI_DB_PASSWORD is required}
NURON_API_DB_PASSWORD: ${NURON_API_DB_PASSWORD:?NURON_API_DB_PASSWORD is required}
volumes:
# Postgres 18+ images store data in a pg_ctlcluster-style versioned subdirectory,
# so the mount point is the parent dir, not .../data (docker-library/postgres#37).
- postgres_data:/var/lib/postgresql
- ./schema/schema.sql:/docker-entrypoint-initdb.d/01-schema.sql:ro
- ./scripts/postgres-healthcheck.sh:/usr/local/bin/nuron-postgres-healthcheck:ro
ports:
# ponytail: host-published Postgres until nuron-ai joins the `nuron` network (NU-005).
- "127.0.0.1:5432:5432"
networks:
- nuron
healthcheck:
test: ["CMD", "sh", "/usr/local/bin/nuron-postgres-healthcheck"]
interval: 5s
timeout: 5s
retries: 10
start_period: 10s
neo4j:
image: neo4j:2026.07.1-community
# unless-stopped: same contract as postgres. cypher-shell authenticates with
# NEO4J_AUTH — a mid-bootstrap crash that leaves auth unusable fails this
# check and stays unhealthy. Docker does not restart on that. Wipe if needed:
# docker compose down -v && docker compose up -d
restart: unless-stopped
environment:
# Any other NEO4J_-prefixed var is converted to a config setting by the image's
# entrypoint, so the password only ever travels inside NEO4J_AUTH -- a second
# NEO4J_PASSWORD var here would be rejected at startup as an unrecognized setting.
NEO4J_AUTH: neo4j/${NEO4J_PASSWORD:?NEO4J_PASSWORD is required}
volumes:
- neo4j_data:/data
ports:
# ponytail: host-published bolt until nuron-ai joins the `nuron` network (NU-005). HTTP
# browser UI (7474) stays commented out -- nothing here needs it.
- "127.0.0.1:7687:7687"
networks:
- nuron
healthcheck:
test: ["CMD-SHELL", "cypher-shell -u neo4j -p \"$${NEO4J_AUTH#*/}\" 'RETURN 1' || { echo 'neo4j auth failed (bootstrap incomplete?). Wipe: docker compose down -v' >&2; exit 1; }"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
# RustFS runs as uid 10001:10001; a fresh named volume is root-owned, so it needs
# chowning once before rustfs can write to it (same fix RustFS's own docker-compose
# examples ship as a "volume-permission-helper" service).
rustfs-init:
image: alpine:3
command: ["chown", "-R", "10001:10001", "/data/rustfs0"]
volumes:
- rustfs_data:/data/rustfs0
networks:
- nuron
# Oneshot. unless-stopped would loop it after a successful chown.
restart: "no"
rustfs:
image: rustfs/rustfs:1.0.0-alpha.99
# unless-stopped: /health is liveness after rustfs-init. A crash-loop is a
# process exit (Docker restarts); a live-but-broken daemon stays unhealthy.
restart: unless-stopped
depends_on:
rustfs-init:
condition: service_completed_successfully
security_opt:
- "no-new-privileges:true"
environment:
RUSTFS_VOLUMES: /data/rustfs0
RUSTFS_ADDRESS: 0.0.0.0:9000
RUSTFS_CONSOLE_ADDRESS: 0.0.0.0:9001
RUSTFS_CONSOLE_ENABLE: "true"
RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY:?RUSTFS_ACCESS_KEY is required}
RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY:?RUSTFS_SECRET_KEY is required}
volumes:
- rustfs_data:/data/rustfs0
ports:
# ponytail: host-published S3 until nuron-ai joins the `nuron` network (NU-004).
- "127.0.0.1:9000:9000"
# Console UI -- uncomment only for local debugging with a GUI client.
# ports:
# - "127.0.0.1:9001:9001"
networks:
- nuron
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9000/health || { echo 'rustfs /health failed. Wipe: docker compose down -v' >&2; exit 1; }"]
interval: 10s
timeout: 5s
retries: 10
start_period: 15s
networks:
nuron:
driver: bridge
volumes:
postgres_data:
neo4j_data:
rustfs_data: