Phase 4 slice 1: backend release image (single worker, non-root) #31
Reference in New Issue
Block a user
Delete Branch "po/phase4-backend-dockerfile"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What — adds the backend release image. Two new files, no application code touched:
backend/Dockerfile— multi-stage likefrontend/Dockerfile: deps stage installs the dependencies from the repo lock (backend/uv.lock,uv sync --frozen --no-dev --no-editable), runtime stage runsuvicorn researchx.api.app:app --host 0.0.0.0 --port 8000 --workers 1as the non-root userresearchx, with the data dir at/var/lib/researchx.backend/.dockerignore— keeps.env*, caches and the local data dir out of the build context.Why — REQ-83 of the owner-directed roadmap: "Dockerfile for the FastAPI backend (single uvicorn worker, non-root)". Tracked on coreci/researchx#30. The frontend has had a release image since v0.1; the backend has none, so there is nothing deployable for the API today.
How to review — two files, in this order:
backend/Dockerfile— the deps stage reads the committed lock, not the index; the runtime stage drops the build toolchain and the dev dependencies, and runs as a non-root user.backend/.dockerignore— secrets and caches stay out of the image.Done looks like: the deploy host builds this image from the
backend/context the waydeploy.shbuilds the frontend, and the container answers on port 8000 as userresearchx.Risk — low: new files only, nothing runs them yet. Two legs this slice deliberately does not close, both named in REQ-83 and both needing application code, not Docker:
/healthzdoes not exist. Every route in the app sits under/api; the deploy health check for the backend has no endpoint until that unauthenticated route is added.RESEARCHX_DATA_DIRis not read by the app. Storage isPath.cwd() / ".researchx"(backend/src/researchx/api/app.py,create_app). The image links that path at/var/lib/researchx, so a volume mounted there works today; the link becomes a no-op once the app reads the variable.Two smaller notes: no uv version is pinned anywhere in the repo, so the image installs a bounded range (
uv>=0.8,<2) — pin it exactly once the deploy host's uv version is known; and no secret is baked into the image (key injection rides REQ-85's hosted live mode).Evidence — repo gate green on
mainat merge commit57528d7473ca(run 58204, backend job 60493 and frontend job 60494 both success); branchpo/phase4-backend-dockerfileoffmain@57528d7473ca. No image build was run: the repo gate does not build images and this seat has no Docker, so the first build is on the deploy host under the deploy.sh extension (REQ-83).TL;DR — closing this one in favour of coreci/researchx#32: the base branch is wrong for phase 4, and two of its notes are wrong for the v0.3 code.
What —
milestone/v0.3-hosted— every v0.3 phase so far landed there (PRs #16..#19) and tags v0.3.0..v0.3.3 are cut from it. This pull request is based onmain(57528d7473), which has diverged from the milestone branch (14 commits only onmain, 8 only on the branch) and still carries the v0.2-era app, so merging here would land the backend image on a branch the phase does not ship from./healthzdoes exist (a plain GET outside/api, never auth-wrapped — D-103), and the mutable data root does come fromRESEARCHX_DATA_DIR(researchx.config.paths.data_root()— D-107). The image in #32 is written against those contracts, with a real healthcheck and a real volume mount.Action — superseded by coreci/researchx#32 (same file set, corrected, based on
milestone/v0.3-hosted@fd3d6c2e03= tag v0.3.3, with the phase-4 gate ported onto that branch). Nothing to merge here.Details — coreci/researchx#32.
Pull request closed