feat(docker): add containerized nginx deployment with runtime base path
Two-stage build: node builds the static bundle, nginx serves it. The bundle is built against a placeholder base token that the entrypoint rewrites to $BASE_URL at start, so one image serves from any path without a rebuild. nginx config caches hashed assets forever, never caches index.html, and applies security headers (CSP, no framing, no referrer) suited to an app that handles cloud credentials client-side. .gitattributes pins LF on the container-consumed files, since core.autocrlf would otherwise give the entrypoint a CRLF shebang. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
# Rendered to /etc/nginx/conf.d/default.conf at startup, with ${BASE_URL} substituted.
|
||||
# See docker/40-ready2blob-base-url.sh.
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
include /etc/nginx/snippets/security-headers.conf;
|
||||
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_min_length 1024;
|
||||
gzip_types text/css application/javascript image/svg+xml application/json;
|
||||
|
||||
# Vite emits content-hashed filenames under assets/ — safe to cache forever.
|
||||
location ${BASE_URL}assets/ {
|
||||
include /etc/nginx/snippets/security-headers.conf;
|
||||
add_header Cache-Control "public, max-age=31536000, immutable" always;
|
||||
}
|
||||
|
||||
# index.html must never be cached, or clients pin to a stale bundle after a redeploy.
|
||||
location = ${BASE_URL}index.html {
|
||||
include /etc/nginx/snippets/security-headers.conf;
|
||||
add_header Cache-Control "no-cache" always;
|
||||
}
|
||||
|
||||
# No `$uri/` here on purpose: if the directory exists but holds no index file,
|
||||
# nginx answers 403 instead of falling through to the fallback.
|
||||
location / {
|
||||
try_files $uri ${BASE_URL}index.html;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user