# ============================================================ # opsxsql - 单镜像多阶段构建(参照 opsx-loki) # 前端 dist + Go 后端 + gh-ost 合并为一个 alpine 运行时镜像 # 非 root 用户运行;/health 健康检查;数据落 /app/data 卷 # ============================================================ # --------------------------------------------------------------- # Stage 1: 前端构建(Node) # --------------------------------------------------------------- FROM node:20-alpine AS frontend-builder WORKDIR /app/frontend COPY frontend/package*.json ./ RUN npm ci --ignore-scripts && npm cache clean --force COPY frontend/ ./ RUN npm run build # --------------------------------------------------------------- # Stage 2: 后端构建(Go,CGO 因 mattn/go-sqlite3 必开) # --------------------------------------------------------------- FROM golang:1.26-alpine AS backend-builder RUN apk add --no-cache git gcc musl-dev ENV GOTOOLCHAIN=local WORKDIR /app/backend COPY backend/go.* ./ RUN go mod download COPY backend/ ./ RUN CGO_ENABLED=1 GOOS=linux go build -ldflags="-s -w" -o /out/opsxsql ./cmd/server/ # --------------------------------------------------------------- # Stage 3: gh-ost 在线变更工具(静态二进制,按架构取包) # --------------------------------------------------------------- FROM alpine:3.20 AS ghost ARG TARGETARCH RUN apk add --no-cache curl && \ case "${TARGETARCH}" in \ arm64) GH_ARCH="arm64" ;; \ *) GH_ARCH="amd64" ;; \ esac && \ curl -fsSL -o /out/gh-ost \ "https://github.com/github/gh-ost/releases/download/v1.1.9/gh-ost-linux-${GH_ARCH}" && \ chmod +x /out/gh-ost # --------------------------------------------------------------- # Stage 4: 运行时镜像 # --------------------------------------------------------------- FROM alpine:3.20 RUN apk --no-cache add ca-certificates tzdata wget sqlite && \ rm -rf /tmp/* /var/cache/apk/* # 非 root 用户 RUN addgroup -g 1000 opsxsql && \ adduser -u 1000 -G opsxsql -s /bin/sh -D opsxsql WORKDIR /app COPY --from=backend-builder --chown=opsxsql:opsxsql /out/opsxsql ./opsxsql COPY --from=ghost --chown=opsxsql:opsxsql /out/gh-ost /usr/local/bin/gh-ost COPY --from=frontend-builder --chown=opsxsql:opsxsql /app/frontend/dist ./dist RUN mkdir -p /app/data && chown -R opsxsql:opsxsql /app/data && \ chmod +x ./opsxsql ENV DIST_DIR=/app/dist \ DB_PATH=/app/data/sqlite3.db \ PORT=9000 \ DEBUG=false \ GH_OST_PATH=/usr/local/bin/gh-ost \ HOME=/home/opsxsql COPY --chown=opsxsql:opsxsql docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh USER opsxsql EXPOSE 9000 VOLUME ["/app/data"] HEALTHCHECK --interval=30s --timeout=5s --retries=3 --start-period=15s \ CMD wget --no-verbose --tries=1 --spider http://localhost:9000/health || exit 1 ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]