Files
agatha 12176471e1 Feat: Add production-grade multi-stage container image for API
Two-stage build (uv builder + python:3.12-slim runtime) with non-root
user (UID 1001), no dev deps, layer-cache-optimised dep install, and
graceful SIGTERM shutdown. Verified by api/tests/build/verify_production_image.sh
covering build, health endpoint, non-root, stdout logging, secret-free
layers, missing-env-var exit, and dep-layer cache hit. All 102 integration
tests still pass; shellcheck clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 19:59:29 +00:00

4.0 KiB

Contract: Production API Container Image

This document defines the observable interface of the reactbin-api-prod container image. Any orchestration layer (Kubernetes manifests, Docker Compose, CI pipeline) MUST be written against this contract.


Network Interface

Property Value
Protocol HTTP/1.1
Port 8000 (TCP)
Bind address 0.0.0.0 (all interfaces inside the container)

Health Check

The container exposes a health check at the existing API health endpoint:

GET /api/v1/health

Success response (200 OK):

{ "status": "ok" }

The container declares a built-in HEALTHCHECK with the following defaults:

Parameter Value
Interval 30s
Timeout 5s
Start period 10s
Retries 3

Orchestrators that define their own probes (e.g. Kubernetes livenessProbe / readinessProbe) SHOULD use this same endpoint.


Required Environment Variables

All configuration is supplied at runtime via environment variables. The image contains no defaults for secret or environment-specific values.

Variable Description Example
JWT_SECRET_KEY HS256 signing key for bearer tokens change-me-long-random-string
OWNER_USERNAME Username of the single owner account owner
OWNER_PASSWORD Password of the single owner account change-me
DATABASE_URL PostgreSQL connection URL (asyncpg scheme) postgresql+asyncpg://user:pass@host:5432/db
S3_ENDPOINT_URL S3-compatible object storage endpoint https://s3.amazonaws.com
S3_BUCKET_NAME Storage bucket name reactbin-prod
S3_ACCESS_KEY_ID Storage access key AKIAIOSFODNN7EXAMPLE
S3_SECRET_ACCESS_KEY Storage secret key wJalrXUtnFEMI/K7MDENG
S3_REGION Storage region us-east-1

Optional environment variables (safe defaults apply):

Variable Default Description
JWT_EXPIRY_SECONDS 86400 Token lifetime in seconds
MAX_UPLOAD_BYTES 52428800 Maximum upload file size (50 MB)
LOGIN_MAX_FAILURES 5 Brute-force lock threshold
LOGIN_WINDOW_SECONDS 300 Failure counting window
LOGIN_COOLDOWN_SECONDS 900 Lock duration after threshold
LOGIN_TRUSTED_PROXY_IPS `` Comma-separated trusted proxy CIDRs
API_BASE_URL (not required at runtime) Used only by client tooling

Startup failure behaviour: If a required variable is absent, the application exits with a non-zero code before accepting any requests. The error is logged to stderr identifying the missing variable.


Signal Handling

Signal Behaviour
SIGTERM Stop accepting new connections; drain in-flight requests; exit 0 within 30s
SIGKILL Immediate termination (OS-level; no graceful drain possible)

Kubernetes should configure terminationGracePeriodSeconds ≥ 30 to allow the full drain window.


Process Identity

Property Value
User appuser
UID 1001
GID 1001
Root privileges None

The container MUST NOT be run with --privileged or as UID 0.


Filesystem

  • Working directory: /app
  • Application source: /app/app/
  • Virtual environment: /app/.venv/
  • No writable state: The container requires no persistent local storage. All state is in PostgreSQL and S3.
  • Read-only root: The container is compatible with --read-only (no writes to the filesystem at runtime).

Logging

All log output is written to stdout (info/debug) and stderr (warnings/errors). No log files are written inside the container. The container runtime log driver captures all output without additional configuration.


Image Tags

Tag pattern Meaning
reactbin-api-prod:latest Latest build from master
reactbin-api-prod:<git-sha> Immutable build for a specific commit

Deployments SHOULD pin to a specific git SHA tag, not latest.