# ---- Stage 1: build the Vue3 SPA ---- # node:22-alpine satisfies package.json engines (^22.18.0 || >=24.12.0). FROM node:22-alpine AS build WORKDIR /app # Install deps first for better layer caching. package-lock.json is committed, # so `npm ci` gives reproducible installs. COPY package.json package-lock.json ./ RUN npm ci # Copy sources and build -> /app/dist COPY . . RUN npm run build # ---- Stage 2: serve the static dist with nginx ---- FROM nginx:stable-alpine # Built SPA -> nginx html root COPY --from=build /app/dist /usr/share/nginx/html # Reverse-proxy + SPA fallback config -> overwrites nginx's stock default.conf COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 # nginx:stable-alpine ships no default healthcheck. Probe `/` (the SPA shell), # NOT /api/health — we want to detect nginx itself being wedged, not a sick # backend (healthy-nginx + sick-backend must not be misreported as unhealthy). # busybox wget is already in the alpine image. HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget -q --spider http://localhost/ || exit 1 # nginx image already has CMD ["nginx", "-g", "daemon off;"]