-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdocker-compose.dev.yml
More file actions
243 lines (230 loc) · 8.09 KB
/
Copy pathdocker-compose.dev.yml
File metadata and controls
243 lines (230 loc) · 8.09 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
# Forge — local development Docker Compose (single-command dev stack).
#
# ONE command brings the whole stack up, healthy, migrated and seeded:
#
# docker compose -f deploy/docker-compose.dev.yml up -d --build --wait
#
# (or `scripts/dev.sh up` / `make dev-up`).
#
# Web UI: http://localhost:3000 API: http://localhost:8000
# Caddy: http://localhost:8080 Docs: http://localhost:8000/docs
#
# Design notes:
# * A fixed project name (`forge-dev`) isolates this stack from any other
# compose project / standalone container on the host.
# * Internal services (db, redis, minio, mcp-gateway) are NOT published to the
# host — services reach them over the compose network by name (db:5432,
# redis:6379, ...), so the host ports 5432/6379/etc. are never touched.
# * Only web (3000), api (8000) and caddy (8080) publish host ports, and every
# host port is env-overridable with a conflict-free default.
# * A one-shot `migrate` service runs `alembic upgrade head` before api/worker
# start; a one-shot `seed` service then seeds the demo workspace. Both are
# idempotent and gate the app tier via `service_completed_successfully`.
# * Every long-running service has a healthcheck so `--wait` blocks until the
# stack is actually ready.
#
# All defaults below are SAFE DEV-ONLY values; override via deploy/.env.dev
# (used automatically by scripts/dev.sh) or the shell environment.
name: forge-dev
# Shared env for the Python services (api / worker / mcp-gateway / migrate / seed).
x-python-env: &python-env
FORGE_ENV: development
FORGE_ENVIRONMENT: development
FORGE_DEBUG: "true"
FORGE_SECRET_KEY: ${FORGE_SECRET_KEY:-dev-only-insecure-secret-change-me-0123456789abcdef}
FORGE_DATABASE_URL: postgresql+psycopg://${POSTGRES_USER:-forge}:${POSTGRES_PASSWORD:-forge}@db:5432/${POSTGRES_DB:-forge}
FORGE_REDIS_URL: redis://redis:6379/0
MCP_GATEWAY_URL: http://mcp-gateway:8001
MINIO_ENDPOINT: http://minio:9000
services:
# --------------------------------------------------------------------- #
# Data tier — internal only (no published host ports) #
# --------------------------------------------------------------------- #
db:
image: pgvector/pgvector:pg16@sha256:ad2e18408bf447f62092a8a5259e7df10505c5a0360bd1a1853ac8b8b0763da2
environment:
POSTGRES_USER: ${POSTGRES_USER:-forge}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-forge}
POSTGRES_DB: ${POSTGRES_DB:-forge}
volumes:
- dev-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-forge} -d ${POSTGRES_DB:-forge}"]
interval: 5s
timeout: 5s
retries: 20
start_period: 10s
redis:
image: redis:7.4-alpine@sha256:6ab0b6e7381779332f97b8ca76193e45b0756f38d4c0dcda72dbb3c32061ab99
command: ["redis-server", "--appendonly", "yes"]
volumes:
- dev-redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 20
minio:
image: minio/minio:RELEASE.2024-10-13T13-34-11Z@sha256:9535594ad4122b7a78c6632788a989b96d9199b483d3bd71a5ceae73a922cdfa
command: ["server", "/data", "--console-address", ":9001"]
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-forge}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-forge-dev-password}
volumes:
- dev-minio-data:/data
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:9000/minio/health/live || exit 1"]
interval: 10s
timeout: 5s
retries: 20
start_period: 10s
# --------------------------------------------------------------------- #
# One-shot init: migrations then demo seed (gate the app tier) #
# --------------------------------------------------------------------- #
migrate:
build:
context: ..
dockerfile: deploy/docker/api.Dockerfile
image: forge/api:dev
command: ["alembic", "-c", "packages/db/alembic.ini", "upgrade", "head"]
environment: *python-env
restart: "no"
depends_on:
db:
condition: service_healthy
seed:
image: forge/api:dev
command: ["python", "-m", "forge_api.scripts.seed"]
environment: *python-env
restart: "no"
depends_on:
migrate:
condition: service_completed_successfully
# --------------------------------------------------------------------- #
# Application tier #
# --------------------------------------------------------------------- #
api:
build:
context: ..
dockerfile: deploy/docker/api.Dockerfile
image: forge/api:dev
command: ["uvicorn", "forge_api.main:app", "--host", "0.0.0.0", "--port", "8000"]
environment:
<<: *python-env
FORGE_CORS_ORIGINS: '["http://localhost:3000","http://localhost:8080"]'
ports:
- "${API_PORT:-8000}:8000"
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
migrate:
condition: service_completed_successfully
healthcheck:
test:
- "CMD-SHELL"
- "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health')\" || exit 1"
interval: 10s
timeout: 5s
retries: 15
start_period: 20s
worker:
build:
context: ..
dockerfile: deploy/docker/worker.Dockerfile
image: forge/worker:dev
command: ["celery", "-A", "forge_worker", "worker", "--loglevel=info"]
environment: *python-env
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
migrate:
condition: service_completed_successfully
healthcheck:
test: ["CMD-SHELL", "celery -A forge_worker inspect ping || exit 1"]
interval: 15s
timeout: 10s
retries: 10
start_period: 30s
mcp-gateway:
build:
context: ..
dockerfile: deploy/docker/mcp-gateway.Dockerfile
image: forge/mcp-gateway:dev
command:
- "uvicorn"
- "forge_mcp_gateway.app:app"
- "--host"
- "0.0.0.0"
- "--port"
- "8001"
environment: *python-env
depends_on:
db:
condition: service_healthy
migrate:
condition: service_completed_successfully
healthcheck:
test:
- "CMD-SHELL"
- "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8001/health')\" || exit 1"
interval: 10s
timeout: 5s
retries: 15
start_period: 20s
web:
build:
context: ..
dockerfile: deploy/docker/web.dev.Dockerfile
image: forge/web:dev
environment:
NODE_ENV: development
NEXT_TELEMETRY_DISABLED: "1"
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://localhost:8000}
ports:
- "${WEB_PORT:-3000}:3000"
depends_on:
api:
condition: service_healthy
healthcheck:
test:
- "CMD-SHELL"
- "node -e \"fetch('http://localhost:3000/').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))\" || exit 1"
interval: 10s
timeout: 10s
retries: 30
start_period: 40s
# --------------------------------------------------------------------- #
# Edge proxy — single entrypoint at http://localhost:8080 #
# --------------------------------------------------------------------- #
caddy:
image: caddy:2.8-alpine@sha256:af32e97399febea808609119bb21544d0265c58a02836576e32a2d082c262c17
command: ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
volumes:
- ./caddy/Caddyfile.dev:/etc/caddy/Caddyfile:ro
- dev-caddy-data:/data
- dev-caddy-config:/config
ports:
- "${CADDY_PORT:-8080}:80"
depends_on:
api:
condition: service_healthy
web:
condition: service_healthy
mcp-gateway:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:80/ >/dev/null 2>&1 || exit 1"]
interval: 10s
timeout: 5s
retries: 10
start_period: 10s
volumes:
dev-db-data:
dev-redis-data:
dev-minio-data:
dev-caddy-data:
dev-caddy-config: