Files
bookorbit/docs/production.md
T

1.9 KiB

Production Deployment (Docker Compose)

This project's production Compose stack is intentionally separate from local development.

1) Configure production environment

Create .env.prod from the example and set real values:

cp .env.prod.example .env.prod

Required fields:

  • APP_IMAGE (immutable tag or digest from CI, for example ghcr.io/<owner>/<repo>:sha-<commit>)
  • POSTGRES_USER
  • POSTGRES_PASSWORD
  • POSTGRES_DB
  • JWT_SECRET
  • APP_URL

2) Deploy

docker compose --env-file .env.prod -f docker-compose.prod.yml pull
docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --wait

What happens:

  • postgres starts with pgvector enabled via init SQL.
  • migrate runs once (node dist/scripts/migrate.js) and must complete successfully.
  • app starts only after DB health is healthy and migration service exits successfully.

3) Roll forward

  1. Update APP_IMAGE in .env.prod to the new immutable image.
  2. Pull + restart:
docker compose --env-file .env.prod -f docker-compose.prod.yml pull
docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --wait

4) Backup strategy

Create a compressed custom-format Postgres backup:

pnpm db:backup:prod

By default this writes to local/backups/.

Recommended cadence:

  • Daily backups
  • Keep at least 7 daily + 4 weekly + 3 monthly snapshots
  • Store a copy off-host

5) Restore strategy

Restore into the live DB:

pnpm db:restore:prod -- local/backups/<file>.dump

Run a non-destructive restore test into a temporary DB:

pnpm db:restore:test:prod -- local/backups/<file>.dump

Run the restore test at least monthly so backup integrity is continuously verified.

6) CI image pipeline

Workflow: .github/workflows/container-image.yml

On main and tag pushes it:

  • builds the Docker image
  • pushes immutable tags to GHCR (sha-*)