From 25ebd947b88937629e57c98169d17ccecd019da0 Mon Sep 17 00:00:00 2001 From: lzh Date: Tue, 23 Dec 2025 13:43:32 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E6=94=B9=E4=B8=BA=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E6=9E=84=E5=BB=BA=EF=BC=8C=E4=BC=A0dist=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=88=B0=E6=9C=8D=E5=8A=A1=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/deploy-web.yaml | 37 ++++-- Dockerfile | 12 +- Dockerfile.deploy | 19 +++ scripts/deploy/README.md | 214 +++++++++++++++++++++++++++++++ scripts/deploy/build-and-push.sh | 68 ++++++++++ 5 files changed, 332 insertions(+), 18 deletions(-) create mode 100644 Dockerfile.deploy create mode 100644 scripts/deploy/README.md create mode 100644 scripts/deploy/build-and-push.sh diff --git a/.gitea/workflows/deploy-web.yaml b/.gitea/workflows/deploy-web.yaml index 1aa66d566..332d989f4 100644 --- a/.gitea/workflows/deploy-web.yaml +++ b/.gitea/workflows/deploy-web.yaml @@ -5,12 +5,11 @@ on: branches: - master paths: - # 仅当以下文件变动时触发构建,避免改个 README 也重新发版 - - 'apps/web-antd/**' - - 'packages/**' - - 'package.json' - - 'pnpm-lock.yaml' - - 'Dockerfile' + # 仅当构建产物 dist 目录变化时触发部署 + # 修改源码不会触发,需要先在本地构建后推送 dist 目录 + - 'apps/web-antd/dist/**' + - 'apps/web-antd/nginx.conf' + - 'Dockerfile.deploy' - '.gitea/workflows/deploy-web.yaml' jobs: @@ -49,7 +48,20 @@ jobs: # 检查 1panel-network 是否存在,如果不存在则创建 docker network inspect 1panel-network > /dev/null 2>&1 || docker network create 1panel-network || true - # 3. 构建并部署 + # 3. 检查构建产物(必须存在) + - name: Check Build Artifacts + run: | + if [ ! -d "apps/web-antd/dist" ] || [ -z "$(ls -A apps/web-antd/dist 2>/dev/null)" ]; then + echo "❌ Error: Build artifacts not found in apps/web-antd/dist" + echo "Please build locally first: pnpm build:antd" + echo "Then run: ./scripts/deploy/build-and-push.sh" + exit 1 + fi + echo "✅ Build artifacts found" + BUILD_SIZE=$(du -sh apps/web-antd/dist | cut -f1) + echo "📊 Build size: $BUILD_SIZE" + + # 4. 构建并部署(只打包,不构建) - name: Build & Deploy Web UI env: # 镜像名称 @@ -59,17 +71,14 @@ jobs: # 宿主机端口 HOST_PORT: 9090 run: | - # --- 构建阶段 --- SHORT_SHA=$(git log -1 --format='%h') FULL_IMAGE_NAME="${IMAGE_NAME}:${SHORT_SHA}" - echo "Building Docker Image: $FULL_IMAGE_NAME..." + echo "🚀 Building Docker Image (deploy only, no build): $FULL_IMAGE_NAME..." - # 使用根目录的 Dockerfile 进行构建 - # Dockerfile 内部使用了多阶段构建,不需要 Runner 安装 Node - # 启用 BuildKit 以支持缓存挂载(加速依赖安装) - # 注意:资源限制已在Dockerfile内部通过并发限制和内存限制实现 - DOCKER_BUILDKIT=1 docker build -t "$FULL_IMAGE_NAME" -f Dockerfile . + # 使用 Dockerfile.deploy,只复制构建产物,不进行构建 + # 这样可以避免服务器资源占用 + DOCKER_BUILDKIT=1 docker build -t "$FULL_IMAGE_NAME" -f Dockerfile.deploy . # 打上 latest 标签 docker tag "$FULL_IMAGE_NAME" "${IMAGE_NAME}:latest" diff --git a/Dockerfile b/Dockerfile index 4dfa1de7a..ddf0eeb07 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,11 +38,15 @@ RUN --mount=type=cache,id=pnpm-store,target=/pnpm/store \ pnpm install --frozen-lockfile --network-concurrency 2 # 限制turbo并发构建,降低资源占用(仅CI/CD构建时生效) -# 并发数设为2,平衡构建速度和资源占用 +# 并发数设为1,Vite构建阶段非常消耗资源,串行构建更稳定 # 降低Node.js内存限制,避免占用过多内存影响其他服务(服务器8GB内存) -# 每个Node进程限制为2GB,2个并发进程共4GB,为系统和其他服务预留4GB -ENV NODE_OPTIONS=--max-old-space-size=2048 -RUN pnpm exec turbo build --filter=@vben/web-antd --concurrency=2 +# 限制为1024MB,为系统和其他服务预留更多内存(约7GB) +# 限制Node.js线程池大小,减少并发线程数,降低CPU占用 +ENV NODE_OPTIONS=--max-old-space-size=1024 +ENV UV_THREADPOOL_SIZE=2 +# 设置垃圾回收更频繁,减少内存峰值 +ENV NODE_OPTIONS="$NODE_OPTIONS --expose-gc" +RUN pnpm exec turbo build --filter=@vben/web-antd --concurrency=1 # ============================== # 2️⃣ 运行阶段 diff --git a/Dockerfile.deploy b/Dockerfile.deploy new file mode 100644 index 000000000..e74369dda --- /dev/null +++ b/Dockerfile.deploy @@ -0,0 +1,19 @@ +# ============================== +# 仅部署阶段 - 不进行构建 +# 用于本地构建后,直接部署构建产物 +# ============================== +FROM nginx:alpine + +# 移除默认配置 +RUN rm /etc/nginx/conf.d/default.conf + +# 复制自定义 Nginx 配置 +COPY apps/web-antd/nginx.conf /etc/nginx/conf.d/default.conf + +# 复制构建产物(从本地构建好的dist目录) +COPY apps/web-antd/dist /usr/share/nginx/html + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] + diff --git a/scripts/deploy/README.md b/scripts/deploy/README.md new file mode 100644 index 000000000..869058703 --- /dev/null +++ b/scripts/deploy/README.md @@ -0,0 +1,214 @@ +# 本地构建+自动部署方案 + +## 📋 快速参考 + +| 操作 | 是否触发 CI/CD | 说明 | +|------|---------------|------| +| 修改源码 | ❌ 否 | 需要先本地构建,再推送 dist | +| 推送 dist 目录 | ✅ 是 | 自动触发部署 | +| 修改 nginx.conf | ✅ 是 | 自动触发部署 | +| 修改 Dockerfile.deploy | ✅ 是 | 自动触发部署 | + +**快速部署命令**: +```bash +./scripts/deploy/build-and-push.sh +``` + +## 方案说明 + +本方案采用**本地构建 + 服务器部署**的方式,避免在服务器上进行资源密集的构建过程,从而解决服务器资源占用问题。 + +**重要提示**: +- ✅ **修改源码不会触发 CI/CD**:只有推送 `dist` 目录时才会触发部署 +- ✅ **必须先本地构建**:在推送前需要在本地执行构建命令 +- ✅ **服务器零构建压力**:服务器只负责轻量级的 Docker 镜像打包,不进行构建 + +## 工作流程 + +``` +本地开发 → 本地构建 → 推送 dist → CI/CD 自动部署 → 服务器运行 + ↓ ↓ ↓ ↓ ↓ +修改源码 pnpm build git push 检测 dist 变化 Docker 打包 +(不触发) (生成 dist) (触发) (自动部署) (不构建) +``` + +详细步骤: +1. **本地开发**:修改源码(`apps/web-antd/src/**`),此时不会触发 CI/CD +2. **本地构建**:在本地执行构建命令,生成 `apps/web-antd/dist` 目录 +3. **推送构建产物**:将 `dist` 目录提交并推送到 Git 仓库 +4. **自动部署**:CI/CD 检测到 `dist` 目录变化,自动部署到服务器 +5. **服务器部署**:服务器只进行 Docker 镜像打包,不进行构建 + +## 使用方法 + +### 方式一:使用自动化脚本(推荐) + +```bash +# 在项目根目录执行 +./scripts/deploy/build-and-push.sh +``` + +脚本会自动: +- 清理旧的构建产物 +- 安装依赖(如果需要) +- 执行构建 +- 检查构建结果 +- 提示是否提交并推送 + +### 方式二:手动操作 + +```bash +# 1. 本地构建 +pnpm build:antd + +# 2. 检查构建结果 +ls -la apps/web-antd/dist + +# 3. 提交并推送 +git add apps/web-antd/dist +git commit -m "chore: build and deploy web-antd" +git push origin master +``` + +## 文件说明 + +- `Dockerfile.deploy`: 仅用于部署的 Dockerfile,不进行构建,只复制构建产物 +- `build-and-push.sh`: 本地构建和推送脚本 +- `.gitea/workflows/deploy-web.yaml`: CI/CD 工作流配置(已修改为仅部署模式) + +## CI/CD 触发条件 + +### ✅ 会触发部署的情况 + +当以下文件变化时会触发自动部署: +- `apps/web-antd/dist/**` - **构建产物目录(主要触发条件)** +- `apps/web-antd/nginx.conf` - Nginx 配置 +- `Dockerfile.deploy` - 部署用 Dockerfile +- `.gitea/workflows/deploy-web.yaml` - CI/CD 配置 + +### ❌ 不会触发部署的情况 + +以下情况**不会**触发 CI/CD: +- 修改源码(`apps/web-antd/src/**`) +- 修改依赖包(`packages/**`) +- 修改 `package.json` 或 `pnpm-lock.yaml` +- 修改原 `Dockerfile`(根目录) +- 修改其他配置文件 + +**注意**:如果只修改了源码,需要先本地构建生成 `dist` 目录,然后推送 `dist` 才会触发部署。 + +## 重要注意事项 + +### 1. 构建产物必须提交到 Git + +**必须确保** `apps/web-antd/dist` 目录被 Git 跟踪,否则 CI/CD 无法检测到变化。 + +**检查方法**: +```bash +# 检查 dist 是否被 Git 跟踪 +git ls-files apps/web-antd/dist + +# 如果输出为空,说明 dist 未被跟踪 +``` + +**解决方法**: +- 如果 `dist` 在 `.gitignore` 中,需要临时移除或使用强制添加: + ```bash + git add -f apps/web-antd/dist + ``` + +### 2. 修改源码后必须重新构建 + +**重要**:修改源码后,CI/CD **不会自动触发**,需要: +1. 本地执行构建:`pnpm build:antd` +2. 推送构建产物:`git add apps/web-antd/dist && git push` + +### 3. 构建环境要求 + +- **Node.js**: >= 20.12.0 +- **pnpm**: >= 10.14.0 +- **网络**: 本地构建需要能够访问 npm/pnpm 仓库 + +### 4. 工作流程建议 + +**推荐流程**: +```bash +# 1. 开发阶段:修改源码(不会触发 CI/CD) +vim apps/web-antd/src/xxx.vue + +# 2. 测试阶段:本地预览 +pnpm dev:antd + +# 3. 构建阶段:生成构建产物 +pnpm build:antd + +# 4. 部署阶段:推送构建产物(触发 CI/CD) +./scripts/deploy/build-and-push.sh +``` + +## 优势 + +✅ **服务器零构建压力**:不占用服务器 CPU/内存/带宽 +✅ **构建速度快**:本地资源充足,构建更快 +✅ **可离线构建**:不依赖服务器网络 +✅ **便于调试**:本地可预览构建结果 +✅ **资源友好**:服务器只负责轻量级的 Docker 镜像打包 + +## 故障排查 + +### 问题:CI/CD 提示构建产物不存在 + +**解决方案**: +1. 检查本地是否成功构建:`ls -la apps/web-antd/dist` +2. 检查 dist 目录是否被 Git 跟踪:`git ls-files apps/web-antd/dist` +3. 如果 dist 在 .gitignore 中,使用强制添加:`git add -f apps/web-antd/dist` + +### 问题:构建失败 + +**解决方案**: +1. 检查 Node.js 版本:`node --version`(需要 >= 20.12.0) +2. 检查 pnpm 版本:`pnpm --version`(需要 >= 10.14.0) +3. 清理并重新安装依赖:`pnpm clean && pnpm install` +4. 查看详细错误信息:`pnpm build:antd --verbose` + +### 问题:推送后 CI/CD 未触发 + +**可能原因**: +1. **只推送了源码,没有推送 dist**:修改源码不会触发 CI/CD + - 解决:先执行 `pnpm build:antd`,然后推送 `dist` 目录 + +2. **dist 目录未被 Git 跟踪**: + ```bash + # 检查 dist 是否被跟踪 + git ls-files apps/web-antd/dist + + # 如果为空,强制添加 + git add -f apps/web-antd/dist + git commit -m "chore: add build artifacts" + git push + ``` + +3. **推送的文件路径不匹配触发条件**: + - 确保推送了 `apps/web-antd/dist/**` 目录 + - 检查 `.gitignore` 是否忽略了 dist + +4. **Git 提交信息包含 `[skip ci]`**: + - 如果提交信息包含 `[skip ci]`,CI/CD 会被跳过 + - 解决:使用其他提交信息 + +5. **Gitea Actions 未启用**: + - 检查 Gitea 仓库设置中 Actions 是否启用 + +### 问题:修改源码后如何部署 + +**解决方案**: +1. 本地构建:`pnpm build:antd` +2. 检查构建结果:`ls -la apps/web-antd/dist` +3. 推送构建产物: + ```bash + git add apps/web-antd/dist + git commit -m "chore: build and deploy web-antd" + git push origin master + ``` +4. 或者使用自动化脚本:`./scripts/deploy/build-and-push.sh` + diff --git a/scripts/deploy/build-and-push.sh b/scripts/deploy/build-and-push.sh new file mode 100644 index 000000000..fa801dead --- /dev/null +++ b/scripts/deploy/build-and-push.sh @@ -0,0 +1,68 @@ +#!/bin/bash + +# 本地构建并推送到仓库的脚本 +# 使用方法: ./scripts/deploy/build-and-push.sh + +set -e + +echo "🚀 Starting local build and push process..." + +# 1. 检查是否在项目根目录 +if [ ! -f "package.json" ]; then + echo "❌ Error: Please run this script from project root" + exit 1 +fi + +# 2. 清理旧的构建产物 +echo "📦 Cleaning old build artifacts..." +rm -rf apps/web-antd/dist + +# 3. 安装依赖(如果需要) +if [ ! -d "node_modules" ]; then + echo "📥 Installing dependencies..." + pnpm install +fi + +# 4. 构建项目 +echo "🔨 Building project..." +pnpm build:antd + +# 5. 检查构建结果 +if [ ! -d "apps/web-antd/dist" ] || [ -z "$(ls -A apps/web-antd/dist)" ]; then + echo "❌ Error: Build failed, dist directory is empty" + exit 1 +fi + +echo "✅ Build successful!" + +# 6. 显示构建产物大小 +BUILD_SIZE=$(du -sh apps/web-antd/dist | cut -f1) +echo "📊 Build size: $BUILD_SIZE" + +# 7. 提交并推送(可选) +read -p "Do you want to commit and push to repository? (y/n) " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + # 检查是否有未提交的更改 + if [ -n "$(git status --porcelain)" ]; then + echo "📝 Staging build artifacts..." + git add apps/web-antd/dist + git add -A # 添加其他更改 + + echo "💾 Committing changes..." + git commit -m "chore: build and deploy web-antd [skip ci]" || true + + echo "📤 Pushing to repository..." + git push origin master + + echo "✅ Build artifacts pushed successfully!" + echo "⏳ Waiting for CI/CD to deploy..." + else + echo "ℹ️ No changes to commit" + fi +else + echo "ℹ️ Skipping git push. You can manually commit and push later." +fi + +echo "✨ Done!" +