feat(deploy): single-image docker-compose and kubernetes install.sh

- multi-stage root Dockerfile (opsx-loki pattern): frontend dist +
  go binary + gh-ost in one alpine image, non-root user, HEALTHCHECK,
  entrypoint warning for missing SECRET_KEY; gin now serves the SPA
  from DIST_DIR (asset/db-logos/favicon passthrough, /api returns JSON
  404, SPA fallback to index.html) - one origin, no CORS surface
- docker-compose.yml rewritten: single service, named data volume,
  no-new-privileges + cap_drop ALL, /health healthcheck, resource
  limits, log rotation; SECRET_KEY required (openssl rand -hex 32),
  JWT_SECRET optional (auto-generated and persisted in prod)
- kubernetes/: install.sh one-command deploy (idempotent secret
  reuse, --nodeport/--ingress flags, rollout wait, backup tips) plus
  namespace/secret/pvc/deployment(single replica + Recreate, probes,
  resource limits, non-root)/service/nodeport/ingress manifests and
  README (sqlite single-writer constraints, snapshot backup)
- docs: README quick-start now has 3 deployment paths; ARCHITECTURE
  ch.14 expanded

single-image runtime verified locally (SPA/assets/api/login coexist
on :9002); full image build left to server (docker hub unreachable
from this machine)
This commit is contained in:
Logan.Li committed 2026-10-26 20:33:26 +08:00
1 parent 13fb3aceb3
commit 0b16488029
15 files changed
+683 -34

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
# ============================================================
# 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"]