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>
This commit is contained in:
22
ui/nginx.conf
Normal file
22
ui/nginx.conf
Normal file
@@ -0,0 +1,22 @@
|
||||
server {
|
||||
listen 8080;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# SPA fallback: all unmatched paths → app shell
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# Long-lived cache for fingerprinted assets
|
||||
location ~* \.(js|css|woff2?|ttf|eot|svg|png|jpg|jpeg|gif|ico)$ {
|
||||
expires 1y;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# Never cache the entry point
|
||||
location = /index.html {
|
||||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user