| # ========================================================= | |
| # STAGE 1: Hermetic Node Compiler and Code Bundler | |
| # ========================================================= | |
| FROM node:20-alpine AS build-engine | |
| WORKDIR /app | |
| # Copy dependency manifests | |
| COPY package*.json ./ | |
| # FIXED: Swapped 'npm ci' for a clean local-layer 'npm install' | |
| # This automatically handles generating full dependency trees dynamically inside Docker | |
| RUN npm install | |
| # Mount compiler processing environments | |
| COPY tailwind.config.js postcss.config.js vite.config.js ./ | |
| COPY index.html ./ | |
| # Mount asset and source directories | |
| COPY public/ ./public/ | |
| COPY src/ ./src/ | |
| # Compile production build distributions into /app/dist | |
| ENV NODE_ENV=production | |
| RUN npm run build | |
| # ========================================================= | |
| # STAGE 2: Hardened, Unprivileged Static Edge Server | |
| # ========================================================= | |
| FROM nginx:alpine-slim | |
| # Enforce system-level wget availability to guarantee health checks survive baseline upgrades | |
| RUN apk add --no-cache wget \ | |
| && rm -rf /usr/share/nginx/html/* \ | |
| && rm -f /etc/nginx/conf.d/default.conf /etc/nginx/nginx.conf | |
| # Inject security configurations into global runtime path | |
| COPY nginx.conf /etc/nginx/nginx.conf | |
| # Extract tree-shaken static assets directly out of Stage 1 dist/ | |
| COPY --from=build-engine /app/dist /usr/share/nginx/html | |
| # Create and register custom temp structures under explicit non-root contexts | |
| RUN mkdir -p /tmp/client_temp /tmp/proxy_temp /tmp/fastcgi_temp /tmp/uwsgi_temp /tmp/scgi_temp \ | |
| && chown -R nginx:nginx /usr/share/nginx/html /var/cache/nginx /var/log/nginx \ | |
| /tmp/client_temp /tmp/proxy_temp /tmp/fastcgi_temp /tmp/uwsgi_temp /tmp/scgi_temp | |
| # Drop all execution privileges cleanly to non-root | |
| USER nginx | |
| EXPOSE 8080 | |
| # Hardened Runtime Health Check evaluating index.html availability securely | |
| HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ | |
| CMD wget -qO- http://localhost:8080/index.html >/dev/null || exit 1 | |
| CMD ["nginx", "-g", "daemon off;"] |