# ---------- Build stage ---------- ARG NODE_VERSION=22 FROM node:${NODE_VERSION}-slim AS build LABEL stage=builder WORKDIR /app # Use production env for deterministic builds of the static site ENV NODE_ENV=production # Copy package manifests and install deps for the build. We include optional # native deps so Rollup/Vite/esbuild native binaries are resolved for the # builder platform. COPY package.json package-lock.json ./ COPY apps/web/package.json apps/web/package.json # Install root workspace deps (including workspace links) RUN npm ci --include=optional --no-audit --no-fund # Ensure the web workspace's dev deps (vite, plugins) are installed too. # This explicitly installs packages for apps/web so `vite` is available. RUN npm ci --workspace=apps/web --include=optional --no-audit --no-fund # Copy source (after deps to leverage layer cache) and build the static site COPY . . RUN npm run build --workspace apps/web # ---------- Production stage ---------- FROM nginx:stable-alpine LABEL stage=production # Prevent index leaks via autoindex RUN rm -f /etc/nginx/conf.d/default.conf || true COPY nginx.conf /etc/nginx/conf.d/default.conf # Copy built static assets from the build stage COPY --from=build /app/dist/apps/web /usr/share/nginx/html # Expose standard HTTP port EXPOSE 80 # Lightweight healthcheck: wget is present in alpine's busybox HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget -qO- --spider http://127.0.0.1:80/ || exit 1 CMD ["nginx", "-g", "daemon off;"]