docker-compose.yml
Rama main · réplica de lectura del repositorio original.
# ANT — full local stack with only Docker installed.
#
# cp .env.example .env # put your provider key in it (or export it)
# docker compose up -d
# open http://localhost:4200
#
# Notes:
# - Redis is NOT published to the host on purpose: `pnpm dev:infra:redis`
# already claims 16379 and the `ant-redis` container name. Debug with
# `docker compose exec redis redis-cli`.
# - The three ant-cli services share one image build (same tag); preview uses
# the Dockerfile's `preview` stage (adds language toolchains for dev servers).
# - Workspaces mount at /cross/workspaces (chowned to the non-root `ant` user
# in the image). The image-default /data/workspaces is NOT chowned — a named
# volume there would be root-owned and Ant would silently fall back to an
# ephemeral in-container path.
# - This compose publishes 4100/4101/4102/4103/4200/4201 — stop `pnpm dev:all` first.
# - :4200 is the app (SPA + control planes); :4201 is the preview/deploy CONTENT
# origin. They are deliberately different origins: content is user-authored, and
# sharing an origin with the control-plane APIs let a deployed document drive
# them with the viewer's session (report H-NEW-001).
name: ant
# Only ant-api carries the `build:` for this image — three services exporting
# the same tag concurrently races under BuildKit ("image already exists").
# ant-realtime / ant-job reference the tag ant-api's build produces.
x-ant-cli-common: &ant-cli-common
image: ant-cli:local
volumes:
- ant-workspaces:/cross/workspaces
depends_on:
redis:
condition: service_healthy
x-ant-env-common: &ant-env-common
ANT_SERVER_MODE: local
ANT_REDIS_URL: redis://redis:6379
ANT_WORKSPACE_BASE_PATH: /cross/workspaces
x-ant-env-llm: &ant-env-llm
# Interpolated from your shell or a root .env file (gitignored).
ANT_ENCRYPTION_KEY: ${ANT_ENCRYPTION_KEY:-} # empty = auto-generated onto the workspace volume
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
GEMINI_API_KEY: ${GEMINI_API_KEY:-}
DEEPSEEK_API_KEY: ${DEEPSEEK_API_KEY:-}
GLM_API_KEY: ${GLM_API_KEY:-}
KIMI_API_KEY: ${KIMI_API_KEY:-}
services:
redis:
image: redis:7-alpine
command: redis-server --appendonly yes
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 12
ant-api:
<<: *ant-cli-common
build:
context: .
dockerfile: packages/ant-cli/Dockerfile
command: ["tsx", "src/composition/server.ts"]
environment:
<<: [*ant-env-common, *ant-env-llm]
PORT: "4100"
ports:
- "4100:4100" # direct access for debugging; UI traffic goes through ant-ui
ant-realtime:
<<: *ant-cli-common
command: ["tsx", "src/infrastructure/realtime/start-realtime-server.ts"]
environment:
<<: *ant-env-common
PORT: "4101"
healthcheck:
# Override the image HEALTHCHECK (it probes :4100, the api port).
test: ["CMD", "node", "-e", "require('http').get('http://localhost:4101/health',(r)=>process.exit(r.statusCode===200?0:1))"]
interval: 30s
timeout: 10s
start_period: 10s
retries: 3
ports:
- "4101:4101"
ant-job:
<<: *ant-cli-common
command: ["tsx", "src/infrastructure/worker/start-job-worker.ts"]
environment:
<<: [*ant-env-common, *ant-env-llm]
ANT_API_URL: http://ant-api:4100 # worker→api HTTP; the localhost default is wrong across containers
healthcheck:
disable: true # no HTTP surface; the inherited :4100 probe would false-FAIL
ant-preview:
<<: *ant-cli-common
image: ant-cli:local-preview
build:
context: .
dockerfile: packages/ant-cli/Dockerfile
target: preview
command: ["tsx", "src/infrastructure/preview/start-preview-server.ts"]
environment:
<<: *ant-env-common
PORT: "4102" # control plane: /projects/* management API
ANT_PREVIEW_CONTENT_PORT: "4103" # user content: preview + deploy proxies
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:4102/health',(r)=>process.exit(r.statusCode===200?0:1))"]
interval: 30s
timeout: 10s
start_period: 10s
retries: 3
ports:
- "4102:4102"
- "4103:4103"
ant-ui:
build:
context: .
dockerfile: packages/ant-ui/Dockerfile
args:
BUILD_ENV: dev # uses the committed .env.development: empty VITE_* = same-origin routing
# Content is served from the :8081 block (published :4201) — a different
# origin from the app and its control planes, on purpose (H-NEW-001).
VITE_PREVIEW_CONTENT_HOST: http://localhost:4201
volumes:
# The image ships no nginx.conf (cloud mounts one from a K8s ConfigMap).
- ./docker/nginx.conf:/etc/nginx/conf.d/default.conf:ro
ports:
- "4200:8080" # app + control planes
- "4201:8081" # preview/deploy CONTENT — separate origin, see docker/nginx.conf
depends_on:
- ant-api
- ant-realtime
- ant-preview
volumes:
redis-data:
ant-workspaces: