Review: Dockerfile: multi-stage node:22-alpine build

review-1088-2026-04-25 Review

review ready

Verdict: READY

Board item #1088 — Dockerfile: multi-stage node:22-alpine build (forgejo_admin/westside-admin#7). Type: Task. Scope is solid, traceability complete, AC testable, fits in a single agent pass.

Template Completeness

  • [x] Type — Task
  • [x] Lineage — depends on scaffolding (#6)
  • [x] Repo — forgejo_admin/westside-admin
  • [x] User Story — story-westside-admin-admin-row-crud (foundational)
  • [x] Context
  • [x] Scope (Tasks use Scope instead of File Targets — correct per template-issue)
  • [x] Acceptance Criteria
  • [x] Test Expectations
  • [x] Constraints
  • [x] Checklist
  • [x] Related

Traceability

  • [x] story:admin-row-crud label — Admin Row CRUD
  • [x] story note verified — story-westside-admin-admin-row-crud exists, listed on project-westside-admin user-stories table
  • [x] arch:deployment label — deployment topology
  • [x] arch note verified — arch-deployment-westside-admin exists, references kaniko→Harbor→kustomize-tag→ArgoCD pipeline this Dockerfile feeds into
  • [x] Forgejo issue — https://forgejo.tail5b443a.ts.net/forgejo_admin/westside-admin/issues/7 (open)
  • [x] type:infra label

File Targets

Task type — no File Targets section required. Scope identifies two new files to create:
  • [x] Dockerfile — to be created at repo root
  • [x] .dockerignore — to be created at repo root
Repo currently has no Dockerfile (verified; repo is empty pending scaffolding ticket #6). No conflicting file paths.

Repo Placement

OK. Issue filed on forgejo_admin/westside-admin, scope is a new file in that same repo. Single-repo change.

Dependencies

  • Hard dep: Scaffolding ticket forgejo_admin/westside-admin#6 (board item #1087). The Dockerfile assumes package.json, npm run build, and a build/index.js output — all produced by #6. #1087 is also backlog; both can be reviewed in parallel but dev work on #1088 cannot start until #1087 lands.
  • Downstream: Woodpecker CI ticket #8 (board item #1094) and pal-e-deployments overlay #133 (board item #1095) consume the image this Dockerfile produces. Image path harbor.tail5b443a.ts.net/forgejo_admin/westside-admin:<sha> matches the deployment manifest expectation in arch-deployment-westside-admin.
  • Documented in the ticket's ### Lineage section.

Acceptance Criteria

All AC are agent-verifiable:
  • docker build succeeds — runnable
  • docker run -p 3000:3000 serves on 3000 — runnable + curlable
  • Image size < 250MB — docker images output
  • No build secrets — docker history output
  • EXPOSE 3000 — Dockerfile inspection
  • HEALTHCHECK on GET /health returns 200 — docker inspect + curl
Minor gap: Constraints require non-root user (UID 1000+), but no AC line item enforces it. Recommend adding an AC bullet so QA verifies via docker run ... id -u.

Blast Radius

  • Reference Dockerfile ~/westside-app/Dockerfile is adapter-static + nginx, NOT adapter-node. The ticket acknowledges this fallback ("if it exists; otherwise mirror the SvelteKit adapter-node official guide"), but the dev agent should be steered to the adapter-node pattern explicitly to avoid copy-pasting the wrong reference. westside-contracts (also adapter-node) may be a closer pattern reference if it has a Dockerfile.
  • Pattern established here will be the template for any future SvelteKit adapter-node service. Worth getting right.
  • HEALTHCHECK requires a /health route to actually exist in the SvelteKit app. Scaffolding ticket #6 does not include a /health route. Either #6 needs to add it, or this Dockerfile's HEALTHCHECK will fail until a later ticket adds the route. Recommend adding a /health route placeholder to #6's scope OR softening the HEALTHCHECK requirement here.

Decomposition Assessment

2 new files, 6 AC, single repo, well-understood pattern. Estimated agent work: under 5 min. No decomposition needed.

Recommendation

Verdict is READY — the ticket can move backlog → todo as-is. The notes below are nice-to-haves for the dev agent, not blockers:
  • [BODY] Add AC line: "Container runs as non-root user (UID 1000+); verify with docker run --rm westside-admin:test id -u returns ≥ 1000." — closes the constraint→AC gap.
  • [BODY] Replace reference hint: westside-app uses adapter-static + nginx. Steer dev agent to the SvelteKit adapter-node official Dockerfile pattern (or westside-contracts if it has one) to avoid wrong-pattern copy-paste.
  • [SCOPE] Coordinate with scaffolding ticket #6: either add a /health route placeholder to #6's scope, or note here that the HEALTHCHECK will be smoke-tested only after a separate health-route ticket lands. Without this, the HEALTHCHECK AC will fail in isolation.
None of these block READY. Dev agent can proceed once #6 merges.