# ──────────────────────────────────────────────────────────────── # Stage 1: Build the React / Vite frontend # ──────────────────────────────────────────────────────────────── FROM node:20-alpine AS frontend-builder WORKDIR /app/frontend # Cache npm install layer separately from source COPY package*.json ./ RUN npm ci --prefer-offline && npm cache clean --force # Copy source and produce the production bundle COPY . . RUN npm run build # ──────────────────────────────────────────────────────────────── # Stage 2: Build the Go backend (statically linked binary) # ──────────────────────────────────────────────────────────────── FROM golang:1.25-alpine AS backend-builder WORKDIR /app # git is required by some go module downloads RUN apk add --no-cache git # Download dependencies first for better layer caching COPY go.mod go.sum ./ RUN go mod download && go mod verify # Copy all source and compile a fully-static binary COPY . . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build \ -ldflags='-w -s -extldflags "-static"' \ -a -installsuffix cgo \ -o server \ ./cmd/server # ──────────────────────────────────────────────────────────────── # Stage 3: Minimal runtime image # ──────────────────────────────────────────────────────────────── FROM alpine:3.19 # Runtime deps: # ca-certificates – HTTPS requests to MongoDB Atlas / Groq # tzdata – timezone support for streak logic # wget – used by the HEALTHCHECK below RUN apk --no-cache add \ ca-certificates \ tzdata \ wget \ && update-ca-certificates # Non-root user (required by HuggingFace Spaces and general best practice) RUN addgroup -g 1001 -S appgroup && \ adduser -u 1001 -S appuser -G appgroup WORKDIR /app # Copy the compiled Go binary COPY --from=backend-builder /app/server . RUN chmod +x server # Copy the built React app — Go serves it as static files from ./dist COPY --from=frontend-builder /app/frontend/dist ./dist # Fix ownership before switching user RUN chown -R appuser:appgroup /app USER appuser # ──────────────────────────────────────────────────────────────── # Runtime configuration # ──────────────────────────────────────────────────────────────── # HuggingFace Spaces requires port 7860. # The Go server reads $PORT at startup and falls back to 7860. ENV PORT=7860 # Required secrets — set these in HuggingFace Space Settings → Variables and secrets: # MONGODB_URI MongoDB Atlas connection string # JWT_SECRET Long random string for signing sessions # GROQ_API_KEY Groq API key for AI features (optional, degrades gracefully) EXPOSE 7860 HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:7860/health || exit 1 CMD ["./server"]