golangLAKEHOUSE/docker-compose.yml
root 54a05d9311 Sprint 4 deployment artifacts: Dockerfile + docker-compose
Parallel deploy target to the systemd units that landed in a59ef5b.
Single image carries all 11 daemons; docker-compose runs one
container per daemon with the same dependency graph as the systemd
units. Useful when systemd isn't available (Mac dev, remote VMs
without root) or when isolation to a private docker network is
preferred.

Dockerfile (multi-stage):
- Builder: golang:1.25-bookworm. DuckDB cgo needs gcc + glibc;
  alpine's musl doesn't link the official duckdb-go bindings cleanly.
- Runtime: debian:bookworm-slim — same libc, much smaller surface.
  Adds ca-certificates (outbound HTTPS to OpenRouter/OpenCode/Kimi),
  curl + jq (in-container healthchecks + smoke probes), tini (PID 1
  signal forwarding so docker stop sends SIGTERM to the daemon, not
  to a wrapper).
- Single image, multiple binaries. Ships all 11 cmd/* + 3 scripts/
  (staffing_workers, playbook_lift, multi_coord_stress) so deployed
  stacks can run reality tests against themselves.
- Non-root runtime user (uid 999 lakehouse). Layout matches
  /usr/local/bin/lakehouse/<daemon> from REPLICATION.md.
- ENTRYPOINT=tini; no default CMD — operators / compose pick
  which daemon explicitly.

docker-compose.yml (11 services):
- Same dependency graph as deploy/systemd/. depends_on with
  service_healthy condition matches Requires= equivalents:
    catalogd → storaged
    ingestd → storaged + catalogd
    queryd → catalogd
    matrixd → embedd + vectord
- Gateway uses bare depends_on (no health condition) — Wants=
  equivalent so single-upstream restart doesn't cascade.
- chatd has per-provider env_file entries (one each for
  ollama_cloud, openrouter, opencode, kimi) — missing files are
  silently OK, matching the systemd unit's EnvironmentFile=- list.
- Persistent state on the lakehouse-state named volume; commented
  driver_opts shows how to bind to a host path for off-volume
  backups.

.dockerignore:
- Excludes bin/ + reports/ + data/ + git metadata + .env files.
- Especially excludes lakehouse.toml/secrets-go.toml/auth.env so
  local dev configs don't accidentally bake into a published image.

REPLICATION.md gains a Docker section between systemd setup and
the logs section. Ten-line copy-paste from "git clone" to
"docker compose up -d", plus a docker-vs-systemd differences
table covering process supervision, logs, restart policy, file
ownership, host networking quirks, and backup targets.

Validation: docker compose config --quiet → exit 0 (with
placeholder env files in place).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 18:58:47 -05:00

181 lines
5.8 KiB
YAML

# Lakehouse-Go — 11-daemon docker-compose deployment.
#
# Same dependency graph as deploy/systemd/, mapped to Compose's
# `depends_on` + healthchecks. Operators MUST provide:
# - lakehouse.toml mounted at /etc/lakehouse/lakehouse.toml
# - secrets-go.toml mounted at /etc/lakehouse/secrets-go.toml
# (mode 0600 on host)
# - auth.env mounted at /etc/lakehouse/auth.env (per ADR-006 —
# required if any service binds non-loopback)
# - MinIO + Ollama reachable from the lakehouse network
#
# Bring up: docker compose up -d
# Tear down: docker compose down
# Logs: docker compose logs -f gateway
# Status: docker compose ps
x-lakehouse-base: &lakehouse-base
image: lakehouse-go:latest
restart: unless-stopped
networks: [lakehouse]
user: "999:999" # matches the lakehouse user baked into the image
volumes:
- ./lakehouse.toml:/etc/lakehouse/lakehouse.toml:ro
- lakehouse-state:/var/lib/lakehouse
env_file:
- ./auth.env
x-healthcheck: &lakehouse-healthcheck
test: ["CMD", "curl", "-sSf", "http://127.0.0.1:$$PORT/health"]
interval: 10s
timeout: 2s
start_period: 5s
retries: 3
services:
storaged:
<<: *lakehouse-base
container_name: lakehouse-storaged
command: ["/usr/local/bin/lakehouse/storaged", "-config", "/etc/lakehouse/lakehouse.toml", "-secrets", "/etc/lakehouse/secrets-go.toml"]
ports: ["3211:3211"]
volumes:
- ./lakehouse.toml:/etc/lakehouse/lakehouse.toml:ro
- ./secrets-go.toml:/etc/lakehouse/secrets-go.toml:ro
- lakehouse-state:/var/lib/lakehouse
environment: [PORT=3211]
healthcheck: *lakehouse-healthcheck
catalogd:
<<: *lakehouse-base
container_name: lakehouse-catalogd
command: ["/usr/local/bin/lakehouse/catalogd", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3212:3212"]
environment: [PORT=3212]
healthcheck: *lakehouse-healthcheck
depends_on:
storaged: { condition: service_healthy }
ingestd:
<<: *lakehouse-base
container_name: lakehouse-ingestd
command: ["/usr/local/bin/lakehouse/ingestd", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3213:3213"]
environment: [PORT=3213]
healthcheck: *lakehouse-healthcheck
depends_on:
storaged: { condition: service_healthy }
catalogd: { condition: service_healthy }
queryd:
<<: *lakehouse-base
container_name: lakehouse-queryd
command: ["/usr/local/bin/lakehouse/queryd", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3214:3214"]
volumes:
- ./lakehouse.toml:/etc/lakehouse/lakehouse.toml:ro
- ./secrets-go.toml:/etc/lakehouse/secrets-go.toml:ro
- lakehouse-state:/var/lib/lakehouse
environment: [PORT=3214]
healthcheck: *lakehouse-healthcheck
depends_on:
catalogd: { condition: service_healthy }
vectord:
<<: *lakehouse-base
container_name: lakehouse-vectord
command: ["/usr/local/bin/lakehouse/vectord", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3215:3215"]
environment: [PORT=3215]
healthcheck: *lakehouse-healthcheck
embedd:
<<: *lakehouse-base
container_name: lakehouse-embedd
command: ["/usr/local/bin/lakehouse/embedd", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3216:3216"]
environment: [PORT=3216]
healthcheck: *lakehouse-healthcheck
# No depends_on — Ollama is operator infra, not a compose service.
# embedd surfaces unreachable Ollama as 502 at request time.
pathwayd:
<<: *lakehouse-base
container_name: lakehouse-pathwayd
command: ["/usr/local/bin/lakehouse/pathwayd", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3217:3217"]
environment: [PORT=3217]
healthcheck: *lakehouse-healthcheck
observerd:
<<: *lakehouse-base
container_name: lakehouse-observerd
command: ["/usr/local/bin/lakehouse/observerd", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3219:3219"]
environment: [PORT=3219]
healthcheck: *lakehouse-healthcheck
matrixd:
<<: *lakehouse-base
container_name: lakehouse-matrixd
command: ["/usr/local/bin/lakehouse/matrixd", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3218:3218"]
environment: [PORT=3218]
healthcheck: *lakehouse-healthcheck
depends_on:
embedd: { condition: service_healthy }
vectord: { condition: service_healthy }
chatd:
<<: *lakehouse-base
container_name: lakehouse-chatd
command: ["/usr/local/bin/lakehouse/chatd", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3220:3220"]
environment: [PORT=3220]
# chatd's per-provider key files — each as its own env_file so a
# missing file is just "this provider unregistered" not a startup
# failure. Same pattern as the systemd unit's EnvironmentFile=- list.
env_file:
- ./auth.env
- ./ollama_cloud.env
- ./openrouter.env
- ./opencode.env
- ./kimi.env
healthcheck: *lakehouse-healthcheck
gateway:
<<: *lakehouse-base
container_name: lakehouse-gateway
command: ["/usr/local/bin/lakehouse/gateway", "-config", "/etc/lakehouse/lakehouse.toml"]
ports: ["3110:3110"]
environment: [PORT=3110]
healthcheck: *lakehouse-healthcheck
# Wants= equivalent in compose: depends_on without
# condition: service_healthy, so a single upstream restart
# doesn't cascade-restart the gateway.
depends_on:
- storaged
- catalogd
- ingestd
- queryd
- vectord
- embedd
- pathwayd
- observerd
- matrixd
- chatd
networks:
lakehouse:
driver: bridge
volumes:
lakehouse-state:
# /var/lib/lakehouse persisted across container restarts. Bind
# to a host path if backups need to live outside the volume:
# driver: local
# driver_opts:
# type: none
# o: bind
# device: /opt/lakehouse-state