# Stage 1: Install dependencies (cached if package-lock.json unchanged) FROM node:24-alpine AS deps WORKDIR /app # Limit Node.js heap to avoid OOM in constrained CI environments ENV NODE_OPTIONS="--max-old-space-size=1024" # Copy package files first for better layer caching COPY package.json package-lock.json* ./ RUN npm ci # Stage 2: Run tests (fails the build if tests fail) FROM deps AS test COPY . . RUN npx vitest run # Stage 3: Build production bundle FROM deps AS builder COPY . . # Skip tsc type-checking (vitest already validated); Vite transpiles via SWC RUN npx vite build # Stage 4: Serve with nginx FROM nginx:alpine # Remove default nginx static files RUN rm -rf /usr/share/nginx/html/* WORKDIR /app COPY --from=builder /app/dist /usr/share/nginx/html COPY --from=builder /app/nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]