# ==================== Stage 1: 前端构建 ==================== FROM node:20-alpine AS ui WORKDIR /ui # 优先拷贝 package.json 命中 layer cache;无 lock 时退回 npm install COPY frontend/package*.json ./ RUN npm config set registry https://registry.npmmirror.com && \ if [ -f package-lock.json ]; then npm ci; else npm install; fi COPY frontend ./ RUN npm run build # ==================== Stage 2: Go 构建 ==================== FROM golang:1.25.8-alpine3.23 AS api WORKDIR /src # 国内可选:RUN go env -w GOPROXY=https://goproxy.cn,direct COPY backend ./ COPY --from=ui /ui/dist ./dist ENV CGO_ENABLED=0 GOOS=linux RUN go mod tidy && \ go build -trimpath -ldflags="-s -w" -o /out/web ./ # ==================== Stage 3: 运行时 ==================== FROM alpine:3.23 RUN apk add --no-cache tzdata ca-certificates && \ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo "Asia/Shanghai" > /etc/timezone && \ apk del tzdata && \ adduser -D -u 1000 app && \ mkdir -p /app/data && \ chown -R app:app /app WORKDIR /app USER app COPY --from=api --chown=app:app /out/web /app/web ENV TZ=Asia/Shanghai \ LISTEN_ADDR=:8080 EXPOSE 8080 CMD ["/app/web"]