Files
reactbin/ui/Dockerfile.prod
agatha 1b3468b72d Feat: Add production-grade multi-stage container image for UI
Two-stage build (node:22-slim builder + nginxinc/nginx-unprivileged:alpine
runtime) with SPA fallback routing, long-lived cache headers for fingerprinted
assets, non-root user (UID 101), and no Node.js toolchain in runtime image
(82 MB vs 329 MB+ single-stage). Verified by ui/tests/build/verify_production_image.sh
covering build, health, SPA routing, non-root, stdout logging, cache-control
headers, SIGTERM exit 0, Node.js absent, secret-free layers, and dep-layer
cache hit. 102 integration tests still pass; shellcheck clean.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 20:18:55 +00:00

31 lines
1.2 KiB
Docker

# syntax=docker/dockerfile:1
# ════════════════════════════════════════════════
# Build stage: install deps and compile Angular app
# ════════════════════════════════════════════════
FROM node:22-slim AS builder
WORKDIR /app
# Layer cache split: deps only (changes rarely)
COPY package.json package-lock.json ./
RUN --mount=type=cache,target=/root/.npm \
npm ci
# Layer cache split: source (changes often)
COPY . .
RUN npm run build
# ════════════════════════════════════════════════
# Runtime stage: minimal nginx serving static assets
# ════════════════════════════════════════════════
FROM nginxinc/nginx-unprivileged:alpine
COPY --from=builder /app/dist/reactbin-ui/browser /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD wget -qO- http://localhost:8080/ || exit 1