# Quickstart: UI Production Image ## Prerequisites - Docker with BuildKit enabled (default in Docker 23+) - `make` available in the shell ## Build the Image ```bash make build-ui-prod # Equivalent: docker build -f ui/Dockerfile.prod ui/ -t reactbin-ui-prod:latest ``` Expected: Build completes in ~2 minutes on first run (npm install), ~15 seconds on subsequent source-only changes. ## Run the Container ```bash docker run --rm -p 4200:8080 reactbin-ui-prod:latest ``` Open http://localhost:4200 — the app shell loads. Navigate to `/library` or `/tags` — the page loads (SPA routing returns `index.html`). ## Verify All Production Checks ```bash make verify-ui-prod ``` This runs `ui/tests/build/verify_production_image.sh`, which exercises all three user stories: ``` [verify] Building reactbin-ui-prod:verify-... [verify] Build OK [verify] Polling health endpoint... [verify] Health check passed [verify] SPA routing OK (/library → 200) [verify] Non-root user OK (UID ) [verify] Stdout logging OK [verify] Graceful shutdown OK (exit 0) [verify] Node.js absent in runtime image OK [verify] No secrets in image layers OK [verify] Dep layer cache hit confirmed (US3 OK) [verify] All checks passed (US1 + US2 + US3). ``` ## Integration Test Scenarios ### Scenario 1: Initial Build (Cold Cache) ```bash docker rmi reactbin-ui-prod:latest 2>/dev/null || true make build-ui-prod ``` Expected: `npm ci` runs fully (~30–90s depending on network). All packages installed from lockfile. ### Scenario 2: Source-Only Rebuild (Warm Cache) ```bash touch ui/src/app/app.component.ts make build-ui-prod ``` Expected: `npm ci` step is CACHED (skipped). Only the Angular compilation runs (~10–20s). ### Scenario 3: Dependency Change (Cache Invalidation) ```bash # Simulate a lockfile change touch ui/package-lock.json make build-ui-prod ``` Expected: `npm ci` runs fresh (cache miss is intentional and correct). ### Scenario 4: SPA Deep-Link Routing ```bash docker run --rm -d -p 4200:8080 --name ui-test reactbin-ui-prod:latest curl -sf http://localhost:4200/library # 200 + index.html curl -sf http://localhost:4200/tags # 200 + index.html curl -sf http://localhost:4200/nonexistent # 200 + index.html (Angular handles 404) docker stop ui-test ``` ### Scenario 5: Non-Root Assertion ```bash docker run --rm reactbin-ui-prod:latest id # Must NOT output uid=0(root) ``` ### Scenario 6: No Node.js in Runtime Image ```bash docker run --rm reactbin-ui-prod:latest node --version 2>&1 # Must exit non-zero (node not found) ```