Problem
Production deployments need a slim, non-root, healthcheck-ready container image. Single-stage Dockerfiles leak build tools and dev deps into the runtime; running as root is a needless attack surface.
Proposed solution
Port Teller's multi-stage Dockerfile, bumping the base to python:3.14-slim. Builder stage: install uv, uv sync --frozen --no-dev. Runtime stage: matching base, create app:app non-root user before COPY (bake ownership at write time), COPY only .venv and src/, set PATH. Add HEALTHCHECK using python -c 'import urllib.request; urllib.request.urlopen(...)' against /api/v1/health. UV_PYTHON_DOWNLOADS=never, UV_PYTHON_PREFERENCE=only-system.
Acceptance criteria
Priority rationale
High: non-root + slim base is the baseline modern practice; image size and CVE surface affect every deploy.
Depends on
#1
Problem
Production deployments need a slim, non-root, healthcheck-ready container image. Single-stage Dockerfiles leak build tools and dev deps into the runtime; running as root is a needless attack surface.
Proposed solution
Port Teller's multi-stage Dockerfile, bumping the base to
python:3.14-slim. Builder stage: install uv,uv sync --frozen --no-dev. Runtime stage: matching base, createapp:appnon-root user before COPY (bake ownership at write time), COPY only.venvandsrc/, setPATH. AddHEALTHCHECKusingpython -c 'import urllib.request; urllib.request.urlopen(...)'against/api/v1/health.UV_PYTHON_DOWNLOADS=never,UV_PYTHON_PREFERENCE=only-system.Acceptance criteria
docker build .succeeds; final image is multi-stage with non-root user.uvicorn src.api.main:appas non-root.HEALTHCHECKreturns healthy when/api/v1/healthreturns 200 (after feat: backend scaffold (FastAPI app, /api/v1/health, /api/v1/echo, sessions) #17).Priority rationale
High: non-root + slim base is the baseline modern practice; image size and CVE surface affect every deploy.
Depends on
#1