Skip to main content

Stack

docker-compose.yml defines:
ServiceRolePort
redisquote cache + pubsub + sponsor caps6379
postgresindexer destination5432 (compose internal) / 5433 (host)
migrateone-shot Drizzle migrationn/a
apiFastify REST + WS8081
indexerSui event pollern/a
quote-workerhot-strike quote pollern/a
resolverOO settlement + auto-settle keeper8082
agent(opt-in) agent runtime8083
All four @darkpool/* services run off the same image. One node:22-slim + corepack pnpm + tsx Dockerfile, no build step, identical runtime to local dev. Compose picks the process via command:.

Bring it up

# Infra first (one-time)
docker compose up -d redis postgres
pnpm --filter @darkpool/server db:migrate

# Whole backend (canonical)
docker compose up -d --build
The one-shot migrate service gates the db consumers via service_completed_successfully so api/indexer never start against an unmigrated db. Verify:
curl -s http://localhost:8081/health | jq
docker compose logs -f api      # or indexer, resolver, …

Agent profile

docker compose --profile agent up -d
# → trading agent on :8083
Multi-instance → multiple compose services (or run additional agents in terminals on different status ports).

After editing backend code

docker compose up -d --build

Stop everything

docker compose down

Reset the database

docker compose down
docker volume rm sui-overflow-26_postgres-data
docker compose up -d postgres
pnpm --filter @darkpool/server db:migrate

Networking

  • Same repo-root .env via env_file:.
  • Only REDIS_URL (redis://redis:6379), DATABASE_URL (postgres://…:5432/darkpool), and the agent’s SERVER_HTTP_URL=http://api:8081 are overridden per-service for in-network DNS.
  • .binary-markets/ is mounted read-only into api + indexer so registry lookups resolve.
  • packageManager: pnpm@8.13.1 is pinned (9.0.0 made corepack pick a pnpm that can’t frozen-install the repo’s v6 lockfile).

Healthchecks

  • api healthcheck = node -e fetch(...) (slim has no curl). Gates the agent via service_healthy.
  • Agent waits for ${SERVER_URL}/health (60s deadline) before its first tick, which covers host-mode boots too.
First live run exposed a startup race (agent’s immediate first tick fired before api listened → “oracle discovery failed: fetch failed”). Fix lives in both layers.

Dockerfile

FROM node:22-slim
WORKDIR /app
RUN corepack enable
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY packages/ ./packages/
COPY scripts/ ./scripts/
COPY tsconfig.base.json ./
RUN pnpm install --frozen-lockfile
# command is provided by compose
No pnpm build step. Every service runs via tsx directly off source. Identical to local dev, which means one less thing to break.