From cb1a9be2c4fbe15dfb831f11ec0421500e4eb19a Mon Sep 17 00:00:00 2001 From: "Logan.Li" Date: Wed, 12 Aug 2026 12:02:29 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E5=A2=9E=E5=8A=A0=20Docker=20?= =?UTF-8?q?=E5=8D=95=E5=AE=B9=E5=99=A8=E9=83=A8=E7=BD=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 生产用 Dockerfile + compose 嵌入前端二进制,run.sh docker 一键构建启动。 Co-authored-by: Cursor --- .dockerignore | 26 ++++++++++++++++++ .env.example | 13 +++++++-- Dockerfile | 66 ++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 11 +++++++- README.md | 13 +++++++++ docker-compose.yml | 36 +++++++++++++++++++++++++ run.sh | 63 ++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 224 insertions(+), 4 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6206f98 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,26 @@ +.git +.zcode +.claude +.env +.env.* +!.env.example +*.md +logs +*.pid +*.log +*.db +*.sqlite +*.sqlite3 +opsx-licence +backend/backend +backend/server +backend/static/* +!backend/static/.gitkeep +frontend/node_modules +frontend/dist +frontend/logs +**/*_test.go +**/coverage.out +.DS_Store +.idea +.vscode diff --git a/.env.example b/.env.example index d602a4b..67ca835 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ # opsx-licence - 环境变量配置模板 # 复制此文件为 .env 并根据需要修改 +# Docker: cp .env.example .env && ./run.sh docker up # ============================================ # 后端配置 (backend) @@ -8,8 +9,8 @@ # 服务器端口 PORT=9001 -# 运行模式: debug / release -GIN_MODE=debug +# 运行模式: debug / release(生产 / Docker 请用 release) +GIN_MODE=release # JWT 密钥(生产环境必须修改!) JWT_SECRET=your-super-secret-key-change-this-in-production @@ -17,6 +18,7 @@ JWT_SECRET=your-super-secret-key-change-this-in-production # 数据库配置 # 可选: sqlite / mysql / postgres DB_DRIVER=sqlite +# 本地开发可用相对路径;Docker Compose 会覆盖为 /data/db.sqlite3 DB_NAME=db.sqlite3 # MySQL 配置(使用 mysql 时填写) @@ -55,6 +57,13 @@ SUCCESS_URL=opsxshell://pro/activated # PEM 私钥仅保存在服务端,切勿下发到客户端或写入仓库 # WAFFO_PRIVATE_KEY_PEM= +# ============================================ +# Docker Compose +# ============================================ +# 宿主机映射端口(容器内固定 9001) +HOST_PORT=9001 +VERSION=latest + # ============================================ # 前端配置 (frontend) # ============================================ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4f03955 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,66 @@ +# opsx-licence — 前端嵌入 Go 单二进制,Docker 部署 +# Stage 1: Node 构建 Vue +# Stage 2: Go(+CGO) 嵌入 static 并编译 +# Stage 3: 精简运行时 +# 署名 Logan.Li + +# ==================== Stage 1: Frontend ==================== +FROM node:20-bookworm-slim AS frontend-builder + +WORKDIR /frontend +ENV NODE_OPTIONS="--max-old-space-size=2048" +RUN npm config set registry https://registry.npmmirror.com + +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci + +COPY frontend/ ./ +RUN npm run build + +# ==================== Stage 2: Backend ==================== +FROM golang:1.24-bookworm AS backend-builder + +WORKDIR /src +ENV GOPROXY=https://goproxy.cn,direct +ENV CGO_ENABLED=1 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + gcc libc6-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY backend/go.mod backend/go.sum ./ +RUN go mod download + +COPY backend/ ./ +RUN rm -rf static && mkdir -p static +COPY --from=frontend-builder /frontend/dist/. ./static/ + +RUN go build -trimpath -ldflags="-s -w" -o /out/opsx-licence . + +# ==================== Stage 3: Runtime ==================== +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates tzdata curl \ + && rm -rf /var/lib/apt/lists/* \ + && useradd --system --uid 10001 --home-dir /app --shell /usr/sbin/nologin opsx + +ENV TZ=Asia/Shanghai \ + PORT=9001 \ + GIN_MODE=release \ + DB_DRIVER=sqlite \ + DB_NAME=/data/db.sqlite3 + +WORKDIR /app +COPY --from=backend-builder /out/opsx-licence /app/opsx-licence + +RUN mkdir -p /data && chown -R opsx:opsx /app /data +USER opsx + +VOLUME ["/data"] +EXPOSE 9001 + +HEALTHCHECK --interval=15s --timeout=3s --start-period=10s --retries=5 \ + CMD curl -fsS "http://127.0.0.1:${PORT}/health" || exit 1 + +ENTRYPOINT ["/app/opsx-licence"] diff --git a/Makefile b/Makefile index dbfeb43..562cc80 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # opsx-licence - Makefile # 提供常用开发命令的快捷方式 -.PHONY: help install dev build build-ui build-api build-binary clean status stop restart lint test +.PHONY: help install dev build build-ui build-api build-binary docker-up docker-down clean status stop restart lint test # 默认显示帮助 help: @@ -13,6 +13,8 @@ help: @echo " make build-ui - 仅构建前端" @echo " make build-api - 仅构建后端" @echo " make build-binary - 构建前端嵌入式单二进制 opsx-licence" + @echo " make docker-up - Docker 构建并启动" + @echo " make docker-down - 停止 Docker 容器" @echo " make test - 运行后端测试" @echo " make lint - 运行代码检查" @echo " make clean - 清理构建产物和日志" @@ -50,6 +52,13 @@ build: build-ui build-api build-binary: ./run.sh build +# Docker 部署 // Logan.Li +docker-up: + ./run.sh docker up + +docker-down: + ./run.sh docker down + # 后端测试 test: @echo "🧪 运行后端测试..." diff --git a/README.md b/README.md index 44813b4..fbb0be8 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,19 @@ cp .env.example .env - 后端:http://localhost:9001 - 默认账号:`admin` / `admin` +### Docker 部署(生产推荐) + +```bash +cp .env.example .env +# 修改 JWT_SECRET、Waffo 等 +./run.sh docker up # 等价于 docker compose up -d --build +./run.sh docker logs +./run.sh docker down +``` + +- 访问:http://localhost:9001(管理后台 + `/api`) +- 数据卷:`licence_data` → 容器内 `/data/db.sqlite3` + ### 构建单二进制 ```bash diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e3d5342 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +# opsx-licence Docker 部署(单容器:管理后台 + /api) +# 用法: +# cp .env.example .env # 填 JWT / Waffo +# docker compose up -d --build +# # 或旧版: docker-compose up -d --build +# 署名 Logan.Li + +services: + opsx-licence: + image: opsx-licence:${VERSION:-latest} + build: + context: . + dockerfile: Dockerfile + container_name: opsx-licence + restart: unless-stopped + ports: + - "${HOST_PORT:-9001}:9001" + env_file: + - .env + environment: + TZ: Asia/Shanghai + PORT: "9001" + GIN_MODE: ${GIN_MODE:-release} + DB_DRIVER: sqlite + DB_NAME: /data/db.sqlite3 + volumes: + - licence_data:/data + healthcheck: + test: ["CMD", "curl", "-fsS", "http://127.0.0.1:9001/health"] + interval: 15s + timeout: 3s + retries: 5 + start_period: 15s + +volumes: + licence_data: diff --git a/run.sh b/run.sh index 99fcdd2..a100be3 100755 --- a/run.sh +++ b/run.sh @@ -1,7 +1,7 @@ #!/bin/bash # opsx-licence 启动脚本 # 一键启动前后端服务,支持日志轮转与单二进制部署 -# 用法: ./run.sh [start|stop|restart|status|frontend|backend|build|binary|help] +# 用法: ./run.sh [start|stop|restart|status|frontend|backend|build|binary|docker|help] set -e @@ -282,6 +282,62 @@ binary_command() { esac } +# ============================================================ +# Docker 部署(生产推荐) +# ============================================================ +compose_cmd() { + if docker compose version >/dev/null 2>&1; then + echo "docker compose" + elif command -v docker-compose >/dev/null 2>&1; then + echo "docker-compose" + else + error "未找到 docker compose / docker-compose" + return 1 + fi +} + +docker_command() { + local sub=${1:-up} + local dc + dc=$(compose_cmd) || return 1 + + if [ ! -f "$SCRIPT_DIR/.env" ]; then + warning "缺少 .env,正在从 .env.example 复制" + cp "$SCRIPT_DIR/.env.example" "$SCRIPT_DIR/.env" + warning "请编辑 .env 修改 JWT_SECRET / Waffo 配置后再部署" + fi + + case "$sub" in + up|start) + info "Docker 构建并启动..." + $dc -f "$SCRIPT_DIR/docker-compose.yml" up -d --build + success "容器已启动: http://localhost:${HOST_PORT:-9001}" + ;; + down|stop) + info "停止 Docker 容器..." + $dc -f "$SCRIPT_DIR/docker-compose.yml" down + ;; + restart) + $dc -f "$SCRIPT_DIR/docker-compose.yml" restart + ;; + rebuild|upgrade) + info "重新构建并滚动升级..." + $dc -f "$SCRIPT_DIR/docker-compose.yml" up -d --build --force-recreate + ;; + logs) + $dc -f "$SCRIPT_DIR/docker-compose.yml" logs -f --tail=200 + ;; + status|ps) + $dc -f "$SCRIPT_DIR/docker-compose.yml" ps + ;; + *) + error "未知 docker 命令: $sub" + echo "用法: ./run.sh docker [up|down|restart|rebuild|logs|status]" + return 1 + ;; + esac +} + # ============================================================ # 命令 # ============================================================ @@ -320,6 +376,7 @@ show_help() { echo " frontend 仅启动前端服务" echo " build 构建嵌入前端的单二进制 $STANDALONE_BIN" echo " binary 管理单二进制服务(start|stop|restart|status|upgrade)" + echo " docker Docker 部署(up|down|restart|rebuild|logs|status)" echo " status 查看服务状态" echo " help 显示帮助信息" echo "" @@ -330,6 +387,7 @@ show_help() { echo " ./run.sh backend # 仅启动后端" echo " ./run.sh build # 生成 ./opsx-licence" echo " ./run.sh binary start # 启动单二进制服务" + echo " ./run.sh docker up # Docker 构建并启动(生产推荐)" } # ============================================================ @@ -389,6 +447,9 @@ main() { binary) binary_command "${2:-start}" ;; + docker) + docker_command "${2:-up}" + ;; status) show_status ;;