# ============================================================ # Stage 1 — Build # Node 22 Alpine: smallest image with full npm support # ============================================================ FROM node:22-alpine AS builder WORKDIR /app # Install dependencies first (layer cache — only re-runs if package.json changes) COPY package.json package-lock.json ./ RUN npm ci # Copy source and build — no VITE_* args needed at build time. # Supabase keys are injected at runtime via docker/entrypoint.sh → window.__ENV__ COPY . . RUN npm run build # ============================================================ # Stage 2 — Serve # Nginx Alpine: ~25MB final image # ============================================================ FROM nginx:alpine AS runner # Replace default nginx config with SPA config COPY nginx.conf /etc/nginx/conf.d/default.conf # Copy built static files from builder COPY --from=builder /app/dist /usr/share/nginx/html # Entrypoint generates env.js from runtime env vars before starting nginx COPY docker/entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh EXPOSE 80 CMD ["/entrypoint.sh"]