# Public API image: builds the public SPA (homepage + search + contribute), # embeds it into the Go read-only server binary, and ships a static scratch # runtime (used where gcr.io/distroless is not reachable). Build context is the # repo root. # Stage 1: build the public SPA. FROM node:22-alpine AS web WORKDIR /web ENV npm_config_registry=https://registry.npmmirror.com COPY public-frontend/package.json public-frontend/package-lock.json* ./ RUN npm ci || npm install COPY public-frontend/ ./ RUN npm run build # Stage 2: build the Go server binary with the SPA embedded. FROM golang:1.23-alpine AS build ENV GOPROXY=https://goproxy.cn,direct WORKDIR /src COPY api/go.mod api/go.sum ./ RUN go mod download COPY api/ ./ RUN rm -rf internal/publicweb/dist && mkdir -p internal/publicweb/dist COPY --from=web /web/dist/ internal/publicweb/dist/ RUN CGO_ENABLED=0 go build -o /out/server ./cmd/server # Stage 3: minimal runtime. FROM scratch COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=build /out/server /server EXPOSE 8080 ENTRYPOINT ["/server"]