feat: 构建cicd | docke部署 | nginx 配置文件

This commit is contained in:
lzh
2025-12-18 12:04:23 +08:00
parent 76198be3d3
commit b2e831155c
4 changed files with 240 additions and 0 deletions

View File

@@ -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}"

42
Dockerfile Normal file
View File

@@ -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;"]

33
apps/web-antd/nginx.conf Normal file
View File

@@ -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;
}
}

72
docs/DEPLOY.md Normal file
View File

@@ -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 <runner-user>`。
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** 查看构建进度。