# syntax=docker/dockerfile:1.7 ############################ # Frontend build (Vite/React) ############################ FROM node:20-alpine AS fe WORKDIR /src/frontend COPY frontend/package*.json ./ RUN npm ci COPY frontend/ . # default Vite outDir is "dist" under CWD RUN npm run build # expose artifacts in a neutral location RUN mkdir -p /out && cp -r dist/* /out/ ############################ # Backend build (Go) ############################ FROM golang:1.22-alpine AS be RUN apk add --no-cache ca-certificates upx git ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ GOPROXY=https://proxy.golang.org,direct \ GOPRIVATE=scm.bstein.dev WORKDIR /src/backend # 1) Copy mod files first for better caching, include both go.mod and go.sum COPY backend/go.mod backend/go.sum ./ # 2) Warm module cache RUN --mount=type=cache,target=/go/pkg/mod go mod download # 3) Copy the rest of the backend sources COPY backend/ . # 4) Bring in the FE assets where the embed expects them # (your code likely has: //go:embed web/dist/**) COPY --from=fe /out ./web/dist # 5) In case code imports added deps not present during step (1), tidy now RUN --mount=type=cache,target=/go/pkg/mod go mod tidy # 6) Build the binary; fail if go build fails. Allow UPX to fail harmlessly. RUN --mount=type=cache,target=/go/pkg/mod \ go build -trimpath -ldflags="-s -w" -o /pegasus ./main.go && \ upx -q --lzma /pegasus || true ############################ # Final, minimal image ############################ FROM gcr.io/distroless/static:nonroot AS final COPY --from=be /pegasus /pegasus USER nonroot:nonroot ENTRYPOINT ["/pegasus"]