# syntax=docker/dockerfile:1.7 # ===================================================================== # Stage 1 — Build the Vite/React app # ===================================================================== FROM docker-mirror.liara.ir/library/node:22-alpine AS builder WORKDIR /app # Install only what's locked, deterministically. # --legacy-peer-deps avoids ERESOLVE failures on bleeding-edge peer ranges # (React 19 / Vite 8 / TS 6 / ESLint 10). COPY package.json package-lock.json ./ RUN npm ci --no-audit --no-fund --legacy-peer-deps # Build the static bundle. # VITE_PANEL_API is inlined into the bundle at build time (Vite reads it during # `npm run build`), so it must be present as an env var here — not at runtime. ARG VITE_PANEL_API=https://cms-steelforesight.liara.run ENV VITE_PANEL_API=$VITE_PANEL_API COPY . . RUN npm run build # ===================================================================== # Stage 2 — Serve with non-root nginx (Hugging Face Spaces compatible) # ===================================================================== # nginx-unprivileged runs as uid 101 by default — required by HF Spaces, # which forbids running as root. FROM docker-mirror.liara.ir/nginxinc/nginx-unprivileged:alpine AS runner # SPA-aware server config that listens on 7860 (HF Spaces default port) COPY --chown=nginx:nginx nginx.conf /etc/nginx/conf.d/default.conf # Static assets produced by `vite build` COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html EXPOSE 7860 # Healthcheck (works both locally and on HF Spaces) HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ CMD wget -qO- http://127.0.0.1:7860/ >/dev/null 2>&1 || exit 1 CMD ["nginx", "-g", "daemon off;"]