# Throughline stack (A6). Core services come up with `docker compose up`. The open-weights LLM server # (GPU + multi-GB weights) is opt-in behind the `llm` profile: `docker compose --profile llm up`. services: postgres: image: postgres:16-alpine environment: POSTGRES_USER: throughline POSTGRES_PASSWORD: throughline POSTGRES_DB: throughline healthcheck: test: ["CMD-SHELL", "pg_isready -U throughline"] interval: 5s timeout: 3s retries: 20 volumes: - pgdata:/var/lib/postgresql/data redis: image: redis:7-alpine healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 20 keycloak: image: quay.io/keycloak/keycloak:25.0 command: ["start-dev", "--import-realm"] environment: KEYCLOAK_ADMIN: admin KEYCLOAK_ADMIN_PASSWORD: admin ports: - "8081:8080" volumes: - ./deploy/keycloak:/opt/keycloak/data/import:ro api: build: . command: ["api"] depends_on: postgres: { condition: service_healthy } redis: { condition: service_healthy } environment: TL_DATABASE_URL: postgresql+psycopg://throughline:throughline@postgres:5432/throughline TL_REDIS_URL: redis://redis:6379/0 TL_OIDC_JWKS_URL: http://keycloak:8080/realms/throughline/protocol/openid-connect/certs TL_OIDC_ISSUER: http://keycloak:8080/realms/throughline TL_OIDC_AUDIENCE: throughline-api TL_IMPORT_ROOT: /data/imports ports: - "8000:8000" healthcheck: test: ["CMD-SHELL", "python -c \"import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://localhost:8000/readyz').status==200 else 1)\""] interval: 10s timeout: 5s retries: 12 volumes: - imports:/data/imports worker: build: . command: ["worker"] depends_on: postgres: { condition: service_healthy } redis: { condition: service_healthy } environment: TL_DATABASE_URL: postgresql+psycopg://throughline:throughline@postgres:5432/throughline TL_REDIS_URL: redis://redis:6379/0 TL_IMPORT_ROOT: /data/imports volumes: - imports:/data/imports # E5 one-command demo: seed a sample project once the DB is up, so `docker compose up` shows real data. seed: build: . command: ["python", "scripts/seed_demo.py"] depends_on: postgres: { condition: service_healthy } environment: TL_DATABASE_URL: postgresql+psycopg://throughline:throughline@postgres:5432/throughline restart: "no" ui: build: ./ui depends_on: api: { condition: service_healthy } ports: - "5173:80" healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:80/ >/dev/null || exit 1"] interval: 10s timeout: 5s retries: 6 # Opt-in (GPU + multi-GB weights): `docker compose --profile llm up`. Default LLM path is key-free # self-hosted open weights via vLLM's OpenAI-compatible server (ADR/runbook ยง1). llm: image: vllm/vllm-openai:latest profiles: ["llm"] command: ["--model", "Qwen/Qwen2.5-7B-Instruct"] ports: - "8001:8000" deploy: resources: reservations: devices: - { driver: nvidia, count: 1, capabilities: ["gpu"] } volumes: pgdata: imports: