Last updated: 2026-05-31
| File | Purpose | How to Use |
|---|---|---|
docker-compose.yml |
Local development | docker compose up -d (standalone) |
docker-compose.base.yml |
Shared image definitions and healthchecks | Never used alone — always combined |
docker-compose.staging.yml |
Staging overlay (pre-built images) | docker compose -f base.yml -f staging.yml up -d |
docker-compose.prod.yml |
Production overlay (restart:always, no ports exposed) | docker compose -f base.yml -f prod.yml up -d |
docker-compose.vpn.yml |
WireGuard VPN service | docker compose -f vpn.yml up -d |
| Service | Image source | Port (dev) | How it gets its code |
|---|---|---|---|
postgres |
Docker Hub postgres:16-alpine |
5432 |
Official image — no code |
keycloak_db |
Docker Hub postgres:16-alpine |
internal | Official image — no code |
keycloak |
quay.io/keycloak:26.1.4 |
8080 |
Official image + realm JSON mounted |
redis |
Docker Hub redis:7-alpine |
6379 |
Official image — no code |
api |
Dev: build from ../rivheal-api / Prod: GHCR image |
8000 |
Dev: hot-reload source mount / Prod: pre-built image |
ml-service |
Dev: build from ../rivheal-ml-service / Prod: GHCR image |
8001 |
Dev: source build / Prod: pre-built image via GitHub Actions |
rasa |
Docker Hub rasa/rasa:3.6.21 |
5005 |
Volume mount: ${RASA_BOT_PATH}:/app |
rasa-actions |
Docker Hub rasa/rasa-sdk:3.6.2 |
5055 |
Volume mount: ${RASA_BOT_PATH}/actions:/app/actions |
traefik |
Docker Hub traefik:v3.2 |
80, 443 |
Prod only — config files mounted |
mongodb |
Docker Hub mongo:7 |
internal | Prod only — no code |
This is the most important thing to understand about the compose setup:
| Pattern | Services | Explanation |
|---|---|---|
| Pre-built image (GHCR) | api, ml-service |
GitHub Actions builds + pushes image → server pulls it. Server never builds. |
| Official image (Docker Hub) | postgres, redis, keycloak, traefik |
No custom code. Docker pulls the published image directly. |
| Official image + volume mount | rasa, rasa-actions |
Uses official Rasa image. Your rasa-bot/ folder is mounted in at runtime. Rasa reads your NLU data and actions from the mount. |
Building a custom Rasa image would require baking the trained model into the image — which means rebuilding every time you update intents or retrain. The volume mount approach is simpler:
rasa-bot/ → git pull on server → rasa train → restart rasa# Start all dev services
cd rivheal-infra && docker compose up -d
# Start only core (postgres + keycloak + redis)
docker compose up -d postgres keycloak redis
# Rebuild API image after code changes
docker compose up -d --build api
# View logs
docker compose logs -f api
docker compose logs -f ml-service
# Run a DB migration inside the API container
docker compose exec api npm run typeorm migration:run
# Open a psql shell
docker compose exec postgres psql -U rivheal rivheal
# Restart a single service
docker compose restart ml-service
export IMAGE_TAG=v1.2.3
# Staging
docker compose \
-f docker-compose.base.yml \
-f docker-compose.staging.yml \
--env-file .env.staging \
up -d --no-deps api
# Production
docker compose \
-f docker-compose.base.yml \
-f docker-compose.prod.yml \
--env-file .env.prod \
up -d --no-deps api