From b2e831155c9ae4f63bddbba7d9ad1a232a117170 Mon Sep 17 00:00:00 2001 From: lzh Date: Thu, 18 Dec 2025 12:04:23 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9E=84=E5=BB=BAcicd=20|=20docke?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=20|=20nginx=20=E9=85=8D=E7=BD=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/deploy-web.yaml | 93 ++++++++++++++++++++++++++++++++ Dockerfile | 42 +++++++++++++++ apps/web-antd/nginx.conf | 33 ++++++++++++ docs/DEPLOY.md | 72 +++++++++++++++++++++++++ 4 files changed, 240 insertions(+) create mode 100644 .gitea/workflows/deploy-web.yaml create mode 100644 Dockerfile create mode 100644 apps/web-antd/nginx.conf create mode 100644 docs/DEPLOY.md diff --git a/.gitea/workflows/deploy-web.yaml b/.gitea/workflows/deploy-web.yaml new file mode 100644 index 000000000..c7e527ce2 --- /dev/null +++ b/.gitea/workflows/deploy-web.yaml @@ -0,0 +1,93 @@ +name: Web UI CI/CD + +on: + push: + branches: + - master + paths: + # 仅当以下文件变动时触发构建,避免改个 README 也重新发版 + - 'apps/web-antd/**' + - 'packages/**' + - 'package.json' + - 'pnpm-lock.yaml' + - 'Dockerfile' + - '.gitea/workflows/deploy-web.yaml' + +jobs: + build-and-deploy: + runs-on: xw-runner + # 使用包含 Docker 客户端的镜像,这样我们可以在容器内构建镜像 (Docker-in-Docker 模式) + container: + image: catthehacker/ubuntu:act-latest + # 这里的 options 很重要,有时候 Runner 需要特权才能操作宿主机的 Docker + # 如果遇到 permission denied,尝试取消注释下一行: + # options: --privileged --user root + + steps: + # 1. 检出代码 + - name: Checkout Code + run: | + # 清理当前目录,防止旧文件干扰 + ls -A1 | xargs rm -rf + + # 拼接 Clone URL (支持 http 和 https) + SERVER_DOMAIN=$(echo "${{ gitea.server_url }}" | sed -E 's|https?://||') + PROTO="http" + if [[ "${{ gitea.server_url }}" == https* ]]; then PROTO="https"; fi + + # 使用 Gitea Token 进行认证 + GIT_URL="${PROTO}://${{ gitea.actor }}:${{ gitea.token }}@${SERVER_DOMAIN}/${{ gitea.repository }}.git" + + echo "Cloning..." + git clone --depth 1 "$GIT_URL" . + git log -1 --format='%h - %s' + + # 2. 准备 Docker 网络 + # 确保所有服务在同一个网络下,方便互相访问 (e.g. 前端反向代理到后端) + - name: Create Docker Network + run: | + docker network create aiot-net || true + + # 3. 构建并部署 + - name: Build & Deploy Web UI + env: + # 镜像名称 + IMAGE_NAME: 'aiot-web-antd' + # 容器名称 + CONTAINER_NAME: aiot-web-antd + # 宿主机端口 (根据 1Panel 规划,这里假设为 8080) + HOST_PORT: 8080 + run: | + # --- 构建阶段 --- + SHORT_SHA=$(git log -1 --format='%h') + FULL_IMAGE_NAME="${IMAGE_NAME}:${SHORT_SHA}" + + echo "Building Docker Image: $FULL_IMAGE_NAME..." + + # 使用根目录的 Dockerfile 进行构建 + # Dockerfile 内部使用了多阶段构建,不需要 Runner 安装 Node + docker build -t "$FULL_IMAGE_NAME" -f Dockerfile . + + # 打上 latest 标签 + docker tag "$FULL_IMAGE_NAME" "${IMAGE_NAME}:latest" + + # --- 部署阶段 --- + echo "Deploying Container: $CONTAINER_NAME..." + + # 停止并删除旧容器 + docker stop $CONTAINER_NAME || true + docker rm $CONTAINER_NAME || true + + # 启动新容器 + # -d: 后台运行 + # --restart always: 开机自启 + # -p: 端口映射 宿主机:容器 + docker run -d \ + --name $CONTAINER_NAME \ + --network aiot-net \ + --restart always \ + -p ${HOST_PORT}:80 \ + "${IMAGE_NAME}:latest" + + echo "✅ Deployment Successful! Access at port ${HOST_PORT}" + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..42e1b9844 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,42 @@ + +# 1. 构建阶段 +FROM node:20-alpine AS builder + +# 设置 npm 镜像源为淘宝源 +RUN npm config set registry https://registry.npmmirror.com + +WORKDIR /app + +# 启用 pnpm (使用 corepack) +RUN corepack enable && corepack prepare pnpm@9.12.3 --activate + +# 单独复制依赖描述文件,利用 Docker 缓存层 +COPY package.json pnpm-lock.yaml turbo.json ./ +# 注意:你需要复制 workspace 下所有的 package.json,这里简单起见复制整个 packages 目录结构可能比较繁琐 +# 更推荐的做法是直接 COPY 所有源码,因为 pnpm lock 已经锁定了版本 +COPY . . + +# 安装依赖 (利用 cache 挂载可以进一步加速,但在 Gitea Runner 中可能需要额外配置,这里暂时不用) +RUN pnpm install --frozen-lockfile + +# 构建指定项目 (根据 package.json 里的 scripts) +# 这里我们构建 antd 版本 +RUN pnpm build:antd + +# 2. 运行阶段 +FROM nginx:alpine + +# 移除默认配置 +RUN rm /etc/nginx/conf.d/default.conf + +# 复制自定义 Nginx 配置 +COPY apps/web-antd/nginx.conf /etc/nginx/conf.d/default.conf + +# 复制构建产物 +# 注意:Vben 5 的产物目录通常在 apps/web-antd/dist +COPY --from=builder /app/apps/web-antd/dist /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] + diff --git a/apps/web-antd/nginx.conf b/apps/web-antd/nginx.conf new file mode 100644 index 000000000..0e547526d --- /dev/null +++ b/apps/web-antd/nginx.conf @@ -0,0 +1,33 @@ +server { + listen 80; + server_name localhost; # 通配符,匹配所有域名(适用于反向代理场景) + + # 开启 gzip 压缩 + gzip on; + gzip_min_length 1k; + gzip_comp_level 6; + gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml; + gzip_vary on; + gzip_disable "MSIE [1-6]\."; + + root /usr/share/nginx/html; + index index.html; + + # 解决 SPA 路由刷新 404 问题 + location / { + try_files $uri $uri/ /index.html; + } + + # 静态资源缓存配置 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + expires 30d; + add_header Cache-Control "public, no-transform"; + } + + # 错误页面 + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} + diff --git a/docs/DEPLOY.md b/docs/DEPLOY.md new file mode 100644 index 000000000..91d927723 --- /dev/null +++ b/docs/DEPLOY.md @@ -0,0 +1,72 @@ +# Gitea CI/CD 部署指南 + +本文档描述了 `aiot-platform-ui` (Web Antd 端) 的自动化构建与部署流程。 + +## 1. 架构说明 + +项目采用 **Gitea Actions + Docker** 进行部署。 + +* **构建方式**:Docker 多阶段构建 (Multi-stage Build)。 + * Stage 1: `node:20-alpine` -> 安装依赖 -> `pnpm build:web-antd` -> 生成 `dist`。 + * Stage 2: `nginx:alpine` -> 复制 `dist` -> 启动 Web 服务。 +* **运行环境**:目标服务器 (安装了 Gitea Runner 和 Docker)。 +* **网络模式**:容器加入 `aiot-net` 网络,端口映射到宿主机。 + +## 2. 前置准备 + +在使用 CI/CD 前,请确保目标服务器满足以下条件: + +1. **安装 Docker**: `docker -v` 可用。 +2. **配置 Gitea Runner**: + * Runner 已注册到 Gitea。 + * Runner 有权限访问 Docker Socket (`/var/run/docker.sock`)。 +3. **创建网络 (可选)**: + ```bash + docker network create aiot-net + ``` + +## 3. 端口规划 + +| 服务名称 | 容器端口 | 宿主机端口 (Host Port) | 说明 | +| :--- | :--- | :--- | :--- | +| **aiot-web-antd** | 80 | **8080** | 前端 Web 服务,请在 1Panel 中反代此端口 | +| aiot-server | 48080 | 48080 | 后端 API 服务 (参考) | + +> **注意**:如果 8080 端口已被占用,请修改 `.gitea/workflows/deploy-web.yaml` 中的 `HOST_PORT` 变量。 + +## 4. 1Panel 配置指南 + +由于容器运行在 `127.0.0.1:8080`,需要在 1Panel (或 Nginx) 中配置反向代理以通过域名访问。 + +1. **进入 1Panel** -> **网站** -> **创建网站**。 +2. **域名**: 填写你的域名 (e.g., `admin.example.com`)。 +3. **类型**: `反向代理`。 +4. **代理地址**: `http://127.0.0.1:8080`。 +5. **提交**。 + +## 5. 常见问题排查 + +### 构建失败:`pnpm install` 很慢或超时 +* **原因**:网络问题。 +* **解法**:Dockerfile 中已配置 npm 淘宝源。如果依然慢,考虑在 Runner 机器上配置透明代理。 + +### 部署失败:`Permission denied` 访问 Docker +* **原因**:Gitea Runner 用户没有 Docker 组权限。 +* **解法**: + 1. 在服务器执行:`sudo usermod -aG docker `。 + 2. 或者在 workflow yaml 中开启 `privileged: true` (不推荐)。 + +### 页面刷新 404 +* **原因**:Nginx 未配置 SPA 重定向。 +* **解法**:检查 `apps/web-antd/nginx.conf` 是否包含 `try_files $uri $uri/ /index.html;`。 + +## 6. 如何触发部署 + +* 修改代码后,推送到 `master` 分支: + ```bash + git add . + git commit -m "feat: 更新功能" + git push origin master + ``` +* 前往 Gitea 仓库页面 -> **Actions** 查看构建进度。 +