pediatric-ai-scribe-v3/docker-compose.yml
Daniel 97454a8941
Some checks failed
Forgejo Android APK / Root app tests (push) Successful in 55s
Forgejo Docker Build / Root app tests (push) Successful in 47s
Forgejo Android APK / Build signed APK (push) Successful in 1m56s
Forgejo Docker Build / Build Docker image (push) Successful in 12s
Forgejo Docker Build / Deploy to the host (push) Failing after 0s
refactor: the clinical index volume is named for what it holds
mcp-server_mcp-data carried the Compose project prefix, which tied its name to a
directory that has since been renamed to clinical-assist-deploy. It is now
clinical-assist-data, named explicitly in both stacks so it no longer depends on
a project name at all.

Migrated rather than renamed, because Docker cannot rename a volume: writers
stopped, 2.9GB copied, then verified before switching — 13265 files both sides,
3080478708 bytes of file content both sides, and an md5 over every file in
sorted order matching exactly. The old volume is kept, and is now referenced by
nothing, so it can be removed once this has run for a while.

Also removed mcp-server_qdrant-data: 1.7GB belonging to a Qdrant deployment that
no longer exists and which no container mounted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
2026-09-11 04:26:04 +02:00

130 lines
5.2 KiB
YAML

services:
pediatric-scribe:
build:
context: .
args:
GIT_REVISION: ${GIT_REVISION:-unknown}
# A deploy sets PED_AI_IMAGE to an immutable, revision-tagged image from the
# registry; a local build leaves it unset and uses the tag build-image.sh
# writes. Either way the running container can be asked what it is:
# /api/build returns the revision baked into it at build time.
image: ${PED_AI_IMAGE:-ped-ai-local:latest}
ports:
- "127.0.0.1:3552:3000"
env_file:
- .env
environment:
# clinical-mcp, not mcp: this host runs several MCP servers and the bare
# name said nothing about which. Same container, added alias.
CLINICAL_ASSISTANT_MCP_URL: http://clinical-mcp:8000/mcp
REDIS_URL: redis://ped-ai-redis:6379
LOKI_URL: http://monitoring-loki:3100
# LITELLM_API_BASE is intentionally not set here: OpenBao supplies
# https://llm.danvics.com and Compose env would override it. The public
# hostname is the deliberate choice for consistency across the estate.
# The cost is not speed (~19ms on calls taking hundreds) — it is that
# AI calls now depend on Caddy, public DNS and edge TLS being up.
# To pin ped-ai to the container network instead, set it here.
TTS_PROVIDER: litellm
LITELLM_TTS_MODEL: local-kokoro-tts
LITELLM_TTS_VOICE: sherpa/kokoro:am_adam
LITELLM_TTS_VOICES: sherpa/kokoro:am_adam,sherpa/kokoro:am_michael,sherpa/kokoro:af_bella,sherpa/kokoro:af_nicole,sherpa/kokoro:bf_emma,sherpa/kokoro:bm_lewis
CLINICAL_ASSISTANT_PROMPT_POOL_TARGET: 1000
LIBRETRANSLATE_URL: ${LIBRETRANSLATE_URL:-http://libretranslate:5000}
DEEPL_API_BASE: ${DEEPL_API_BASE:-https://api.deepl.com/v2}
GENERATED_IMAGES_S3_ENDPOINT: http://assets:9000
GENERATED_IMAGES_S3_REGION: us-east-1
GENERATED_IMAGES_S3_BUCKET: generated-images
GENERATED_IMAGES_S3_ACCESS_KEY_FILE: /run/secrets/generated-images-access-key
GENERATED_IMAGES_S3_SECRET_KEY_FILE: /run/secrets/generated-images-secret-key
# Recordings are kept for 24 hours; the same MinIO, its own bucket. The
# app key carries a second policy covering only audio-backups, so these
# can reuse the mounted credentials (see scripts/enable-audio-backup-bucket.js).
AUDIO_BACKUPS_S3_ENDPOINT: http://assets:9000
AUDIO_BACKUPS_S3_REGION: us-east-1
AUDIO_BACKUPS_S3_BUCKET: audio-backups
AUDIO_BACKUPS_S3_ACCESS_KEY_FILE: /run/secrets/generated-images-access-key
AUDIO_BACKUPS_S3_SECRET_KEY_FILE: /run/secrets/generated-images-secret-key
volumes:
- scribe-logs:/app/data/logs
- clinical-assistant-mcp-data:/app/mcp-data:ro
- /home/danvics/docker/personal-assistant-storage-milvus/secrets/images-access-key:/run/secrets/generated-images-access-key:ro
- /home/danvics/docker/personal-assistant-storage-milvus/secrets/images-secret-key:/run/secrets/generated-images-secret-key:ro
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
container_name: pediatric-ai-scribe
networks:
- default
- danvics_mcp
- danvics_monitoring
- ped-ai-storage-assets
- danvics_translate
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/api/health"]
interval: 30s
timeout: 10s
retries: 5
start_period: 20s
postgres:
# Digest-pinned, so a rebuilt environment gets this exact Postgres. If a
# newer pg16 image ships a different ICU library, the startup drift check in
# src/db/database.js auto-REINDEXes and refreshes the collation version;
# pinning means that only happens when this line is deliberately changed.
image: pgvector/pgvector:pg16@sha256:00ba258a66dac104fd5171074a0084462a64a1369d8513f3d0a634e2f24d15bc
environment:
POSTGRES_DB: pedscribe
POSTGRES_USER: pedscribe
POSTGRES_PASSWORD: ${DB_PASSWORD:-pedscribe}
volumes:
- pgdata:/var/lib/postgresql/data
restart: unless-stopped
container_name: pedscribe-db
healthcheck:
test: ["CMD-SHELL", "pg_isready -U pedscribe"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
redis:
image: redis:8-alpine@sha256:d146f83b1e0f02fc27c26a50cee39338c736674c5959db84363e6ae3cd9e02d2
command: redis-server --appendonly yes
restart: unless-stopped
container_name: ped-ai-redis
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- default
- danvics_mcp
volumes:
pgdata:
scribe-logs:
redis-data:
clinical-assistant-mcp-data:
external: true
name: clinical-assist-data
networks:
danvics_mcp:
external: true
danvics_monitoring:
external: true
ped-ai-storage-assets:
external: true
name: personal-assistant-storage-milvus_assets
# LibreTranslate's own service network, owned by the libretranslate project.
# ped-ai used to join open-webui's stack network purely to resolve this one
# hostname, which coupled a clinical app to an unrelated stack's lifecycle.
danvics_translate:
external: true