Skip to Content

Deployment

The backend ships as a Docker image whose entrypoint is start.sh, serving on port 8080. The same codebase runs in three roles: the API service, a migration job, and Celery workers.

Container

Build from the repository root:

build-image.sh
docker build -t rhesis-backend:latest -f apps/backend/Dockerfile .

Run it with an env file (see Environment configuration for the variables it expects):

run-container.sh
docker run -p 8080:8080 --env-file ./apps/backend/.env.docker rhesis-backend:latest

start.sh loads .env in local mode, applies migrations via migrate.sh when a database is configured, then starts the server (Gunicorn with Uvicorn workers in production, Uvicorn otherwise).

Migrations

In cloud deployments, migrations run as a separate job (its image entrypoint is migrate.sh, running alembic upgrade head), and the API service sets SKIP_MIGRATIONS=true so it does not migrate on boot. This keeps schema changes to a single controlled step.

Make migrations backward compatible so a new revision can run before the new code is fully rolled out. To roll a schema change back:

rollback-migration.sh
alembic downgrade -1

Workers

Celery workers deploy as their own service from the worker image, sharing the broker and result backend (BROKER_URL, CELERY_RESULT_BACKEND). Scale workers independently of the API. See Background tasks.

Google Cloud Run

The production target is Cloud Run. Deploy the API service, run the migration job separately, and connect Cloud SQL:

deploy-cloud-run.sh
gcloud run deploy rhesis-backend \
--image gcr.io/project-id/rhesis-backend \
--region us-central1 \
--add-cloudsql-instances project-id:region:instance \
--set-env-vars "DB_HOST=/cloudsql/project-id:region:instance,SKIP_MIGRATIONS=true"

The image is a standard container, so it also runs on other platforms (AWS ECS, Azure Container Apps, plain Docker) given the same environment variables.

Operations

  • HealthGET /health returns {"status": "ok"}; use it as the container health check.
  • Logs — the application logs to stdout/stderr; set JSON_LOGGER_ENABLED=true for structured logs (see Architecture).
  • Rollback — redeploy the previous image; reverse migrations only if the new revision was not backward compatible.
  • Secrets — supply JWT_SECRET_KEY, database, and OAuth credentials through the platform’s secret manager, not the image.