-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
169 lines (162 loc) · 6.81 KB
/
Copy pathdocker-compose.yml
File metadata and controls
169 lines (162 loc) · 6.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
services:
api:
build: .
container_name: braindb_api
restart: unless-stopped
networks:
- local-network
# Starts the bundled DB first when the internal-db profile is active
# (COMPOSE_PROFILES=internal-db in .env). With the profile inactive the
# dependency is skipped entirely — external-DB setups are unaffected.
# `required: false` needs Docker Compose >= 2.20.
depends_on:
braindb_db:
condition: service_healthy
required: false
environment:
# Set DATABASE_URL in .env to use your own Postgres (external mode).
# Leave it unset with COMPOSE_PROFILES=internal-db and the api connects
# to the bundled braindb_db service below.
DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-braindb}:${POSTGRES_PASSWORD:-braindb}@braindb_db:5432/${POSTGRES_DB:-braindb}}
API_PORT: ${API_PORT:-8000}
HF_TOKEN: ${HF_TOKEN:-}
LLM_PROFILE: ${LLM_PROFILE:-deepinfra}
AGENT_MODEL: ${AGENT_MODEL:-}
# OpenAI-compatible profile (Ollama / LM Studio / copilot-api / vLLM):
OPENAI_BASE_URL: ${OPENAI_BASE_URL:-}
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
NVIDIA_NIM_API_KEY: ${NVIDIA_NIM_API_KEY:-}
DEEPINFRA_API_KEY: ${DEEPINFRA_API_KEY:-}
VLLM_API_KEY: ${VLLM_API_KEY:-}
AGENT_VERBOSE: ${AGENT_VERBOSE:-false}
# Orphan freshness gate (the orphan SQL runs in this api process, not in
# the scheduler): an entity is wiki-eligible only once created_at is
# older than this many minutes, so still-ingesting subjects settle first.
WIKI_FRESHNESS_MINUTES: ${WIKI_FRESHNESS_MINUTES:-30}
# Optional custom-profile prompt shaping (wiki maintainer/writer). Empty
# by default -> the composition helper is a strict no-op and prompts are
# the baked-in defaults. Set CUSTOM_PROFILE in .env to activate.
CUSTOM_PROFILE: ${CUSTOM_PROFILE:-}
extra_hosts:
# Lets self-hosted profiles (e.g. vllm_workstation) reach a server bound
# to the Docker host's loopback. Docker Desktop sets this implicitly;
# the explicit form keeps the file portable to Linux Docker Engine.
- "host.docker.internal:host-gateway"
ports:
- "${API_PORT:-8000}:${API_PORT:-8000}"
volumes:
- .:/app
# Note: NO `--reload` in the api command. With the bind mount (`.:/app`)
# in dev, `--reload` causes uvicorn to restart on every .py edit, which
# interrupts in-flight LLM calls (the scheduler logs `Connection refused`
# during the ~20-30s embedding-model reload). Code changes are applied
# explicitly via `docker compose up -d --no-deps --force-recreate api` —
# the operator picks the moment. Anyone who wants dev-style live reload
# can override this command via `docker compose run` or a personal
# `docker-compose.override.yml`.
command: >
sh -c "alembic upgrade head && uvicorn braindb.main:app --host 0.0.0.0 --port ${API_PORT:-8000}"
watcher:
build: .
container_name: braindb_watcher
restart: unless-stopped
depends_on:
- api
networks:
- local-network
environment:
BRAINDB_API_URL: http://api:${API_PORT:-8000}
INGEST_POLL_INTERVAL: ${INGEST_POLL_INTERVAL:-7}
volumes:
- .:/app
command: python -m braindb.ingest_watcher
# Bundled Postgres (pgvector) — exists ONLY when the internal-db profile is
# active, i.e. when .env contains COMPOSE_PROFILES=internal-db. Without that
# line this service is invisible to every compose command and external-DB
# setups behave exactly as before. Named braindb_db (not "postgres") so its
# DNS name can't collide with a user's own Postgres on local-network.
# POSTGRES_* values are baked into the volume on FIRST boot; to reset:
# docker rm -f braindb_db && docker volume rm braindb_pgdata
braindb_db:
image: pgvector/pgvector:pg17
container_name: braindb_db
profiles: ["internal-db"]
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-braindb}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-braindb}
POSTGRES_DB: ${POSTGRES_DB:-braindb}
ports:
# Loopback only — for inspecting the DB from the host (psql/adminer).
# The stack itself talks to braindb_db over the docker network and does
# not need this mapping. Change POSTGRES_PORT in .env if 5435 is taken.
- "127.0.0.1:${POSTGRES_PORT:-5435}:5432"
volumes:
- braindb_pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-braindb} -d ${POSTGRES_DB:-braindb}"]
interval: 5s
timeout: 3s
retries: 10
networks:
- local-network
# Always-on wiki maintenance sidecar — same posture as `watcher`. It loops
# cron -> maintain -> write so wikis self-organise from entities with zero
# manual steps. To run without it (e.g. cost control), start the stack
# excluding this service or scale it to 0 — exactly as you would the watcher.
wiki_scheduler:
build: .
container_name: braindb_wiki_scheduler
restart: unless-stopped
depends_on:
- api
networks:
- local-network
environment:
BRAINDB_API_URL: http://api:${API_PORT:-8000}
WIKI_ENABLED: ${WIKI_ENABLED:-true}
WIKI_INTERVAL: ${WIKI_INTERVAL:-60}
volumes:
- .:/app
command: python -m braindb.wiki_scheduler
# Generic custom-profile ingestor supervisor — DORMANT unless CUSTOM_PROFILE
# is set in .env. For each active profile that ships an `ingestor.py` it runs
# that script as an isolated subprocess (restart-on-exit); with no active
# profile it sleeps and makes zero calls. This is what lets a single switch
# (CUSTOM_PROFILE) bring up prompt-shaping AND a profile's ingestor at once,
# while this base file stays profile-agnostic. See custom-profiles/README.md.
profile_runner:
build: .
container_name: braindb_profile_runner
restart: unless-stopped
depends_on:
- api
networks:
- local-network
environment:
BRAINDB_API_URL: http://api:${API_PORT:-8000}
CUSTOM_PROFILE: ${CUSTOM_PROFILE:-}
volumes:
- .:/app
command: python -m braindb.profile_runner
# Read-only browser UI (frontend/ — plain static files, no build step).
# Loopback-only on purpose: the UI's API calls go to http://localhost:8000
# from the BROWSER, so publishing this port beyond loopback wouldn't make
# the app usable remotely anyway. Change FRONTEND_PORT in .env if taken.
frontend:
image: nginx:alpine
container_name: braindb_frontend
restart: unless-stopped
ports:
- "127.0.0.1:${FRONTEND_PORT:-8642}:80"
volumes:
- ./frontend:/usr/share/nginx/html:ro
networks:
- local-network
volumes:
# Data volume for the bundled internal DB (internal-db profile only).
braindb_pgdata:
name: braindb_pgdata
networks:
local-network:
external: true