From b8582ba3e9048a45cf811004772e56ffe26f9e68 Mon Sep 17 00:00:00 2001 From: brother7 <7brother7@gmail.com> Date: Tue, 14 Jul 2026 19:37:34 +0800 Subject: [PATCH] docs: plan web container implementation --- .../plans/2026-07-14-web-container.md | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 docs/superpowers/plans/2026-07-14-web-container.md diff --git a/docs/superpowers/plans/2026-07-14-web-container.md b/docs/superpowers/plans/2026-07-14-web-container.md new file mode 100644 index 0000000..82237e9 --- /dev/null +++ b/docs/superpowers/plans/2026-07-14-web-container.md @@ -0,0 +1,141 @@ +# Web Container Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add a production frontend image so `docker build -t xqkqueue-web: ./web` succeeds and React client-side routes work behind Kubernetes Ingress. + +**Architecture:** A Node.js 22 Alpine build stage installs locked pnpm dependencies and creates the Vite `dist` output. An Nginx Alpine runtime stage serves that output on port 80 and falls back to `index.html` for client-side routes; Kubernetes Ingress routes `/api/*` directly to the API Service. + +**Tech Stack:** Node.js 22, pnpm 10.17.0, Vite 7, Nginx 1.28 Alpine, Docker + +## Global Constraints + +- Keep the Docker build context as `./web`. +- Serve the frontend on container port 80. +- Do not proxy `/api` in the web container; Kubernetes Ingress owns API routing. +- Use `pnpm install --frozen-lockfile` for reproducible dependency resolution. +- Do not modify frontend business code or add Kubernetes manifests. + +--- + +### Task 1: Production web image and SPA server + +**Files:** +- Create: `web/Dockerfile` +- Create: `web/nginx.conf` +- Create: `web/.dockerignore` + +**Interfaces:** +- Consumes: `web/package.json`, `web/pnpm-lock.yaml`, the Vite source tree, and a Kubernetes Ingress that sends non-API paths to port 80. +- Produces: a static Nginx image exposing port 80, with Vite assets in `/usr/share/nginx/html` and SPA fallback for unknown non-file paths. + +- [ ] **Step 1: Reproduce the missing build definition** + +Run from the repository root: + +```bash +docker build -t xqkqueue-web:verify ./web +``` + +Expected before implementation: FAIL with `failed to read dockerfile: open Dockerfile: no such file or directory`. + +- [ ] **Step 2: Add the multi-stage Dockerfile** + +Create `web/Dockerfile`: + +```dockerfile +FROM node:22-alpine AS build +WORKDIR /app +RUN corepack enable && corepack prepare pnpm@10.17.0 --activate +COPY package.json pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile +COPY . . +RUN pnpm build + +FROM nginx:1.28-alpine +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/dist /usr/share/nginx/html +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] +``` + +- [ ] **Step 3: Add SPA-aware Nginx configuration** + +Create `web/nginx.conf`: + +```nginx +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } +} +``` + +- [ ] **Step 4: Exclude local and generated files from the build context** + +Create `web/.dockerignore`: + +```dockerignore +node_modules +dist +coverage +playwright-report +test-results +*.log +*.tsbuildinfo +.DS_Store +.idea +.vscode +``` + +- [ ] **Step 5: Verify the existing production frontend build** + +Run: + +```bash +pnpm --dir web build +``` + +Expected: TypeScript checks and the Vite production build finish with exit code 0 and write `web/dist/index.html`. + +- [ ] **Step 6: Build the container image** + +Run: + +```bash +docker build --progress=plain -t xqkqueue-web:verify ./web +``` + +Expected: exit code 0, including successful `pnpm install --frozen-lockfile`, `pnpm build`, and Nginx runtime stages. + +- [ ] **Step 7: Verify root and client-side route responses** + +Run: + +```bash +docker run --rm -d --name xqkqueue-web-verify -p 18080:80 xqkqueue-web:verify +curl --fail http://127.0.0.1:18080/ +curl --fail http://127.0.0.1:18080/admin +docker stop xqkqueue-web-verify +``` + +Expected: both requests return the Vite application HTML with HTTP 200, and the verification container stops cleanly. + +- [ ] **Step 8: Review and commit the implementation** + +Run: + +```bash +git diff --check +git status --short +git add web/Dockerfile web/nginx.conf web/.dockerignore +git commit -m "build: add frontend container image" +``` + +Expected: only the three intended web container files are committed.