name: helix-foundry x-app: &app build: . image: helix-foundry:local restart: unless-stopped volumes: - foundry-data:/data environment: &env ENCRYPTION_KEY: ${ENCRYPTION_KEY:?Run scripts/setup.sh first} INTERNAL_KEY: ${INTERNAL_KEY:?Run scripts/setup.sh first} APP_ORIGIN: ${PUBLIC_ORIGIN:-http://localhost:3001} HELIX_URL: http://helix:8080 EXECUTOR_URL: http://executor:3002 OLLAMA_URL: ${MODEL_ENDPOINT:-http://ollama:11434} # How long the model stays in memory after a question (Ollama keep_alive). MODEL_KEEP_ALIVE: ${MODEL_KEEP_ALIVE:-30s} INLINE_WORKER: "false" # Listens on the container network; the port is published on loopback only. ALLOW_NETWORK_ACCESS: "true" DATA_DIR: /data # The executor's time limits, which the API waits for. See the executor. EXECUTOR_QUERY_TIMEOUT: ${EXECUTOR_QUERY_TIMEOUT:-} EXECUTOR_JOB_TIMEOUT: ${EXECUTOR_JOB_TIMEOUT:-} # Bytes in one transaction's HelixDB write (docs/OPERATIONS.md). HELIX_WRITE_LIMIT: ${HELIX_WRITE_LIMIT:-} networks: [default, execution] depends_on: helix: condition: service_started services: app: <<: *app environment: <<: *env NEON_CLIENT_ID: ${NEON_CLIENT_ID:-} NEON_CLIENT_SECRET: ${NEON_CLIENT_SECRET:-} SUPABASE_CLIENT_ID: ${SUPABASE_CLIENT_ID:-} SUPABASE_CLIENT_SECRET: ${SUPABASE_CLIENT_SECRET:-} PLANETSCALE_CLIENT_ID: ${PLANETSCALE_CLIENT_ID:-} PLANETSCALE_CLIENT_SECRET: ${PLANETSCALE_CLIENT_SECRET:-} # When Docker runs out of memory, a higher oom_score_adj is stopped first: # the model, then a request, then the worker, and HelixDB last # (docs/OPERATIONS.md#memory). No mem_limit: Node sizes its heap from it, # and a 2g limit caps the heap near 1.1 GB, which the graph read exceeds # on large workspaces. oom_score_adj: 300 ports: - "127.0.0.1:${PUBLIC_PORT:-3001}:3001" healthcheck: test: [ "CMD", "node", "-e", "fetch('http://127.0.0.1:3001/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))", ] interval: 15s timeout: 5s retries: 10 worker: <<: *app command: ["node", "--import", "tsx", "apps/api/src/worker.ts"] oom_score_adj: 200 executor: <<: *app command: ["node", "--import", "tsx", "services/executor/src/server.ts"] environment: INTERNAL_KEY: ${INTERNAL_KEY:?Run scripts/setup.sh first} DATA_DIR: /data EXECUTOR_HOST: 0.0.0.0 EXECUTOR_PORT: 3002 DUCKDB_MEMORY: 512MB # Each can be set in .env; empty means the default. See "Deployment # limits" in docs/OPERATIONS.md. # Disk each job may fill with spill files under /data/scratch, such as # 20GB. Unset, DuckDB stops a job at 90% of the free disk space. DUCKDB_SPILL_LIMIT: ${DUCKDB_SPILL_LIMIT:-} # Disk a publication query may fill with result rows, as JSON lines # (2GB by default). EXECUTOR_RESULT_LIMIT: ${EXECUTOR_RESULT_LIMIT:-} # Seconds a query (120 by default) and an import, pipeline or # publication query (900 by default) may take, queue included. EXECUTOR_QUERY_TIMEOUT: ${EXECUTOR_QUERY_TIMEOUT:-} EXECUTOR_JOB_TIMEOUT: ${EXECUTOR_JOB_TIMEOUT:-} mem_limit: 2g oom_score_adj: 300 pids_limit: 128 cap_drop: [ALL] security_opt: ["no-new-privileges:true"] networks: [execution] helix: # Moving this pin can be one way. The first time HelixDB v0.0.10 or later opens # the data, it upgrades the index storage, and v0.0.9 and earlier then refuse # the database. Installations upgrade with scripts/upgrade.sh, which backs up # first and asks before it starts a new HelixDB image. The development # docker run commands in README.md, AGENTS.md and docs/GUIDE.md use the same # image, and tests/scripts.test.ts checks that they match. image: ghcr.io/helixdb/helixdb:v0.0.12@sha256:f22b50fdab8fadbf8b5a881e656f293fdf5c688bad018f503b8dbc2f0f29543d restart: unless-stopped environment: HELIX_DATA_DIR: /var/lib/helix # No hard limit: the database is the one service that must not be killed. # The reservation keeps its working set from being reclaimed for others. mem_reservation: ${HELIX_MEMORY_RESERVATION:-2g} volumes: - helix-data:/var/lib/helix ollama: image: ollama/ollama:0.17.7 profiles: [local] restart: unless-stopped environment: OLLAMA_NUM_PARALLEL: 1 OLLAMA_MAX_LOADED_MODELS: 1 OLLAMA_NO_CLOUD: "1" OLLAMA_KEEP_ALIVE: ${MODEL_KEEP_ALIVE:-30s} # qwen3:4b uses about 3.3 GB with an 8K context and more with longer # prompts. Above the limit the model fails with an error; HelixDB keeps # running. mem_limit: ${OLLAMA_MEMORY_LIMIT:-6g} oom_score_adj: 500 volumes: - model-data:/root/.ollama model-init: image: curlimages/curl:8.12.1 profiles: [local] restart: on-failure depends_on: [ollama] command: [ "-fsS", "--retry", "30", "--retry-delay", "3", "--retry-connrefused", "http://ollama:11434/api/pull", "-d", '{"model":"qwen3:4b","stream":false}', ] networks: execution: internal: true volumes: foundry-data: helix-data: model-data: