memory/docker-compose.yaml
2025-11-03 22:53:19 +00:00

220 lines
6.6 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# --------------------------------------------------------------------- networks
networks:
kbnet:
# internal overlay NOT exposed
driver: bridge
# --------------------------------------------------------------------- secrets
secrets:
postgres_password: { file: ./secrets/postgres_password.txt }
openai_key: { file: ./secrets/openai_key.txt }
anthropic_key: { file: ./secrets/anthropic_key.txt }
ssh_private_key: { file: ./secrets/ssh_private_key }
ssh_public_key: { file: ./secrets/ssh_public_key }
ssh_known_hosts: { file: ./secrets/ssh_known_hosts }
# --------------------------------------------------------------------- volumes
volumes:
db_data: {} # Postgres
qdrant_data: {} # Qdrant
redis_data: {} # Redis
# ------------------------------ X-templates ----------------------------
x-common-env: &env
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_DB: 0
REDIS_PASSWORD: ${REDIS_PASSWORD}
QDRANT_HOST: qdrant
DB_HOST: postgres
DB_PORT: 5432
FILE_STORAGE_DIR: /app/memory_files
TZ: "Etc/UTC"
x-worker-base: &worker-base
build:
context: .
dockerfile: docker/workers/Dockerfile
restart: unless-stopped
networks: [ kbnet ]
security_opt: [ "no-new-privileges=true" ]
depends_on: [ postgres, redis, qdrant ]
env_file: [ .env ]
environment: &worker-env
<<: *env
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
# DSNs are built in worker entrypoint from user + pw files
QDRANT_URL: http://qdrant:6333
OPENAI_API_KEY_FILE: /run/secrets/openai_key
ANTHROPIC_API_KEY_FILE: /run/secrets/anthropic_key
VOYAGE_API_KEY: ${VOYAGE_API_KEY}
DISCORD_COLLECTOR_SERVER_URL: ingest-hub
DISCORD_COLLECTOR_PORT: 8003
secrets: [ postgres_password, openai_key, anthropic_key, ssh_private_key, ssh_public_key, ssh_known_hosts ]
read_only: true
tmpfs:
- /tmp
- /var/tmp
- /home/kb/.ssh:uid=1000,gid=1000,mode=700
cap_drop: [ ALL ]
volumes:
- ./memory_files:/app/memory_files:rw
logging:
options: { max-size: "10m", max-file: "3" }
user: kb
# ================================ SERVICES ============================
services:
# ----------------------------------------------------------------- data layer
postgres:
image: postgres:15
restart: unless-stopped
networks: [ kbnet ]
environment:
<<: *env
POSTGRES_USER: kb
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
POSTGRES_DB: kb
secrets: [ postgres_password ]
volumes:
- db_data:/var/lib/postgresql/data:rw
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U kb" ]
interval: 10s
timeout: 5s
retries: 5
security_opt: [ "no-new-privileges=true" ]
migrate:
build:
context: .
dockerfile: docker/migrations.Dockerfile
networks: [kbnet]
depends_on:
postgres:
condition: service_healthy
environment:
<<: *env
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
secrets: [postgres_password]
volumes:
- ./db:/app/db:ro
redis:
image: redis:7.2-alpine
restart: unless-stopped
networks: [ kbnet ]
command: ["redis-server", "--save", "", "--appendonly", "no", "--requirepass", "${REDIS_PASSWORD}"]
volumes:
- redis_data:/data:rw
healthcheck:
test: [ "CMD", "redis-cli", "--pass", "${REDIS_PASSWORD}", "ping" ]
interval: 15s
timeout: 5s
retries: 5
security_opt: [ "no-new-privileges=true" ]
cap_drop: [ ALL ]
user: redis
qdrant:
image: qdrant/qdrant:v1.14.0
restart: unless-stopped
networks: [ kbnet ]
volumes:
- qdrant_data:/qdrant/storage:rw
tmpfs:
- /tmp
- /var/tmp
- /qdrant/snapshots:rw
healthcheck:
test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/localhost/6333 && echo -e 'GET /readyz HTTP/1.0\\r\\n\\r\\n' >&3 && timeout 2 cat <&3 | grep -q ready"]
interval: 15s
timeout: 5s
retries: 5
security_opt: [ "no-new-privileges=true" ]
cap_drop: [ ALL ]
# ------------------------------------------------------------ API / gateway
api:
build:
context: .
dockerfile: docker/api/Dockerfile
args:
SERVER_URL: "${SERVER_URL:-http://localhost:8000}"
SESSION_COOKIE_NAME: "${SESSION_COOKIE_NAME:-session_id}"
restart: unless-stopped
networks: [kbnet]
depends_on: [postgres, redis, qdrant]
environment:
<<: *env
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
QDRANT_URL: http://qdrant:6333
SERVER_URL: "${SERVER_URL:-http://localhost:8000}"
VITE_SERVER_URL: "${SERVER_URL:-http://localhost:8000}"
STATIC_DIR: "/app/static"
VOYAGE_API_KEY: ${VOYAGE_API_KEY}
ENABLE_BM25_SEARCH: false
OPENAI_API_KEY_FILE: /run/secrets/openai_key
ANTHROPIC_API_KEY_FILE: /run/secrets/anthropic_key
secrets: [postgres_password, openai_key, anthropic_key]
volumes:
- ./memory_files:/app/memory_files:rw
healthcheck:
test: ["CMD-SHELL", "curl -fs http://localhost:8000/health || exit 1"]
interval: 15s
timeout: 5s
retries: 5
ports:
- "8000:8000"
# ------------------------------------------------------------ Celery workers
worker:
<<: *worker-base
environment:
<<: *worker-env
QUEUES: "backup,email,ebooks,discord,comic,blogs,forums,maintenance,notes,scheduler"
ingest-hub:
<<: *worker-base
build:
context: .
dockerfile: docker/ingest_hub/Dockerfile
environment:
<<: *worker-env
DISCORD_BOT_TOKEN: ${DISCORD_BOT_TOKEN}
DISCORD_NOTIFICATIONS_ENABLED: ${DISCORD_NOTIFICATIONS_ENABLED:-true}
DISCORD_COLLECTOR_ENABLED: true
volumes:
- ./memory_files:/app/memory_files:rw
tmpfs:
- /tmp
- /var/tmp
- /var/log/supervisor
- /var/run/supervisor
deploy: { resources: { limits: { cpus: "0.5", memory: 512m } } }
# ------------------------------------------------------------ database backups
backup:
image: postgres:15 # Has pg_dump, wget, curl
networks: [kbnet]
depends_on: [postgres, qdrant]
env_file: [ .env ]
environment:
<<: *worker-env
secrets: [postgres_password]
volumes:
- ./tools/backup_databases.sh:/backup.sh:ro
entrypoint: ["/bin/bash"]
command: ["/backup.sh"]
profiles: [backup] # Only start when explicitly called
security_opt: ["no-new-privileges=true"]
# ------------------------------------------------------------ watchtower (auto-update)
# watchtower:
# image: containrrr/watchtower
# restart: unless-stopped
# command: [ "--schedule", "0 0 4 * * *", "--cleanup" ]
# volumes: [ "/var/run/docker.sock:/var/run/docker.sock:ro" ]
# networks: [ kbnet ]