# MilkWay ERP — single image hosting backend (Go) + frontend (PWA) on :7860. # Designed for Hugging Face Docker Spaces (runs as non-root UID 1000). # ---------- Stage 1: build the Go backend ---------- FROM golang:1.25-alpine AS build WORKDIR /src # Cache module downloads. COPY backend/go.mod backend/go.sum ./ RUN go mod download # Build a static binary. COPY backend/ ./ RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/server ./cmd/server # ---------- Stage 2: build the PWA frontend ---------- # NOTE: the path is `frontend/PWA` — lowercase `frontend`, uppercase `PWA`. # Docker builds on Linux (case-sensitive); the dev box is Windows (case-insensitive), # so the casing here MUST match exactly what's committed (`frontend/PWA`). FROM node:20-alpine AS web WORKDIR /web # Build-time config baked into the bundle by Vite. # VITE_DEFAULT_ORG_ID — fixed org for admin/employee login (override per Space). # VITE_API_URL — empty = same-origin "/api" in prod (Go serves both). ARG VITE_DEFAULT_ORG_ID=1 ARG VITE_API_URL="" # Install deps first (cached unless the lockfile changes). COPY frontend/PWA/package.json frontend/PWA/package-lock.json ./ RUN npm ci # Copy the rest of the PWA source and build the production bundle into /web/dist. COPY frontend/PWA/ ./ ENV VITE_DEFAULT_ORG_ID=${VITE_DEFAULT_ORG_ID} \ VITE_API_URL=${VITE_API_URL} RUN npm run build # ---------- Stage 3: runtime ---------- FROM alpine:3.20 RUN apk add --no-cache ca-certificates tzdata \ && adduser -D -u 1000 appuser WORKDIR /app COPY --from=build /out/server /app/server # Serve the built PWA (this is STATIC_DIR). The Go static handler does SPA # fallback (index.html for non-/api) and 404 JSON for unknown /api/*. COPY --from=web /web/dist /app/frontend # Hugging Face Spaces expects the app on 7860. Profile defaults to staging; # override APP_PROFILE=live (and set DATABASE_URL) via Space secrets/variables. ENV PORT=7860 \ STATIC_DIR=/app/frontend \ APP_PROFILE=staging EXPOSE 7860 USER appuser CMD ["/app/server"]