Skip to content

Docker Compose Reference

This documents docker-compose.yml at the repository root as it exists today — it is not a proposal or a rewrite. If the file changes, this page may drift; treat the compose file itself as the source of truth and this page as an annotated map to it.

Note: the repo also has a second compose file, docker-compose.yaml (.yaml, not .yml), used for RaiSE's own internal team infrastructure (daemon + server + postgres, including the rai-agent Telegram bot). That file is not the self-hosted deployment target — self-hosted operators only need the server + database, which is exactly what docker-compose.yml provides.

Services

postgres

postgres:
  image: pgvector/pgvector:pg17
  environment:
    POSTGRES_USER: rai
    POSTGRES_DB: rai
    POSTGRES_PASSWORD: dev
  ports:
    - "5432:5432"
  volumes:
    - postgres_data:/var/lib/postgresql/data
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U rai -d rai"]
    interval: 5s
    timeout: 3s
    retries: 5
  • Image: pgvector/pgvector:pg17 — PostgreSQL 17 with the pgvector extension pre-installed (used by semantic search features elsewhere in raise-server; not required by the export endpoints in this story, but bundled since it's the same database).
  • Default credentials (rai / dev, database rai) are for local/dev use. Change POSTGRES_PASSWORD before exposing this anywhere beyond localhost — either edit the compose file directly or override via a docker-compose.override.yml.
  • server won't start until this service's healthcheck passes (depends_on: postgres: condition: service_healthy) — this is what prevents the classic "connection refused" race on first boot.
  • The named volume raise-commons-dev-pgdata persists data across docker compose down / up cycles. It is not removed by down alone — only docker compose down -v or docker volume rm deletes it. See backup-restore.md.

server

server:
  build:
    context: .
    target: server
  environment:
    RAI_DATABASE_URL: postgresql+asyncpg://rai:dev@postgres:5432/rai
    RAI_ENV: development
    RAI_PORT: "8080"
    RAI_LOG_LEVEL: DEBUG
    RAI_COOKIE_SECURE: "false"
    UVICORN_RELOAD: "true"
    RAI_STRIPE_SECRET_KEY: ${RAI_STRIPE_SECRET_KEY:-}
    RAI_STRIPE_PRICE_MONTHLY: ${RAI_STRIPE_PRICE_MONTHLY:-}
    RAI_STRIPE_PRICE_ANNUAL: ${RAI_STRIPE_PRICE_ANNUAL:-}
    RAI_STRIPE_WEBHOOK_SECRET: ${RAI_STRIPE_WEBHOOK_SECRET:-}
  depends_on:
    postgres:
      condition: service_healthy
  ports:
    - "8080:8080"
  volumes:
    - ./packages/raise-server/src:/app/packages/raise-server/src:ro
  • build.target: server — builds the server stage of the repo's multi-stage Dockerfile. This is the same image used for Fly dev/staging/production; self-hosted is not a fork.
  • The volumes: mount (source tree, read-only) plus UVICORN_RELOAD=true gives hot-reload for local development. Remove both for a real self-hosted deployment — you want the code baked into the image at build time, not mounted from a host path that may not match the image's installed dependencies.
  • RAI_STRIPE_* variables default to empty via the ${VAR:-} shell substitution syntax — billing endpoints self-disable (503) rather than crash when these are unset. Self-hosted deployments generally leave these empty (see installation.md § 4, plans/licensing).
  • On boot, entrypoint.sh runs alembic upgrade head before starting uvicorn (this path is only skipped when FLY_APP_NAME or K_SERVICE env vars are present — neither applies to docker compose up) — so a fresh docker compose up always ends with an up-to-date schema, no manual migration step required.

Common overrides

Create a docker-compose.override.yml (Compose merges it automatically, no -f flag needed) rather than editing docker-compose.yml directly, so you can pull upstream changes without merge conflicts:

# docker-compose.override.yml
services:
  postgres:
    environment:
      POSTGRES_PASSWORD: "a-real-secret"
    ports: []  # don't expose 5432 on the host at all

  server:
    environment:
      UVICORN_RELOAD: "false"
      RAI_LOG_LEVEL: INFO
      RAI_COOKIE_SECURE: "true"
    volumes: []  # drop the dev source-mount; run the baked-in image code

Commands you'll actually use

Command Effect
docker compose up -d --build Build (if needed) and start both services, detached
docker compose logs -f server Follow server logs (migrations, request logs)
docker compose ps Container status + healthcheck state
docker compose down Stop and remove containers — data volume persists
docker compose down -v Stop, remove containers, and delete the data volume — destructive
docker compose exec server bash Shell into the running server container
docker compose exec postgres psql -U rai -d rai psql into the database