docs: 更新 CI 部署文档至 v5.3.0

同步实际部署配置变更:
- Docker Compose 使用 network_mode: host 避免 VPC 冲突
- Act Runner config 补充 options + valid_volumes 挂载配置
- 移除 systemd 不必要的 BindPaths
- CI health check 改用 bun fetch
- 新增 Docker bridge/VPC 冲突和 health check 故障排查
This commit is contained in:
Wang Zhuoxuan 2026-04-18 04:23:16 +08:00
parent 9d1f52d95b
commit b75a7ada75

View File

@ -361,6 +361,11 @@ runner:
container: container:
# 容器使用宿主机网络(解决容器无法访问 127.0.0.1:3200 Gitea 的问题) # 容器使用宿主机网络(解决容器无法访问 127.0.0.1:3200 Gitea 的问题)
network: "host" network: "host"
# 挂载宿主机目录到 job 容器CI deploy 步骤需要读取 docker-compose.yml
options: "-v /opt/duoqi-api:/opt/duoqi-api"
# 允许挂载的 volume 白名单
valid_volumes:
- /opt/duoqi-api
# 不强制每次拉取镜像(国内网络下减少失败风险) # 不强制每次拉取镜像(国内网络下减少失败风险)
force_pull: false force_pull: false
``` ```
@ -379,9 +384,6 @@ ExecStart=/usr/local/bin/act_runner daemon --config /opt/act-runner/config.yaml
Restart=always Restart=always
Environment=HOME=/root Environment=HOME=/root
# 关键:挂载 Docker socket让 job 容器能访问宿主机的 Docker daemon
BindPaths=/var/run/docker.sock:/var/run/docker.sock
[Install] [Install]
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
@ -395,6 +397,11 @@ systemctl start act-runner
systemctl status act-runner systemctl status act-runner
``` ```
> **注意**act_runner 是宿主机原生运行的二进制,不是容器。它本身已有完整的文件系统和网络访问权限。
> - **不需要** `BindPaths` 挂载 Docker socket宿主机进程可直接访问
> - **不需要** `BindPaths` 挂载 `/opt/duoqi-api`(同上)
> - job 容器需要访问宿主机目录,通过 `config.yaml` 中的 `container.options``valid_volumes` 配置
### 环境隔离策略 ### 环境隔离策略
#### RDS 数据库隔离 #### RDS 数据库隔离
@ -472,21 +479,22 @@ LOG_LEVEL=debug
**服务器 compose 文件** `/opt/duoqi-api/docker-compose.yml` **服务器 compose 文件** `/opt/duoqi-api/docker-compose.yml`
> 代码库中对应文件为 `docker-compose.prod.yml`,部署时手动重命名为 `docker-compose.yml`
```yaml ```yaml
version: '3.8' # 使用 host 网络模式,避免 Docker bridge 子网与阿里云 VPC 内网 IP 段冲突
services: services:
# ===== 生产环境 ===== # ===== 生产环境 =====
api-prod: api-prod:
build: build:
context: /opt/gitea/data/git/repositories/admin/duoqi-api.git context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: duoqi-api:prod image: duoqi-api:prod
container_name: duoqi-api-prod container_name: duoqi-api-prod
restart: unless-stopped restart: unless-stopped
network_mode: host
env_file: .env.prod env_file: .env.prod
ports:
- "3000:3000"
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"] test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s interval: 30s
@ -503,17 +511,16 @@ services:
limits: limits:
memory: 400M memory: 400M
# ===== 测试环境(按需启停) ===== # ===== 测试环境(Docker profiles 按需启停) =====
api-test: api-test:
build: build:
context: /opt/gitea/data/git/repositories/admin/duoqi-api.git context: .
dockerfile: Dockerfile dockerfile: Dockerfile
image: duoqi-api:test image: duoqi-api:test
container_name: duoqi-api-test container_name: duoqi-api-test
restart: "no" # 不自动重启,手动控制 restart: "no"
network_mode: host
env_file: .env.test env_file: .env.test
ports:
- "3001:3001"
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3001/health"] test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
interval: 30s interval: 30s
@ -530,7 +537,7 @@ services:
limits: limits:
memory: 300M memory: 300M
profiles: profiles:
- test # 使用 profiles 按需启停 - test
``` ```
**启停命令:** **启停命令:**
@ -621,9 +628,11 @@ git push origin main
| 生产部署手动确认 | 防止误操作,确保人工验证后才上线 | | 生产部署手动确认 | 防止误操作,确保人工验证后才上线 |
| 使用 Gitea Actions | 兼容 GitHub Actions 语法,学习成本低 | | 使用 Gitea Actions | 兼容 GitHub Actions 语法,学习成本低 |
| Runner 使用 `network: host` | 容器共享宿主机网络,解决容器无法访问 Gitea 的问题 | | Runner 使用 `network: host` | 容器共享宿主机网络,解决容器无法访问 Gitea 的问题 |
| API 容器使用 `network_mode: host` | 避免 Docker bridge 默认子网172.x.0.0/16与阿里云 VPC 内网 IP 段冲突 |
| Runner 使用 `github_mirror` | 从 gitea.com 镜像拉取 Actions解决国内无法访问 GitHub 的问题 | | Runner 使用 `github_mirror` | 从 gitea.com 镜像拉取 Actions解决国内无法访问 GitHub 的问题 |
| 自定义 Runner 镜像bun + git + docker CLI | 避免 checkout REST API 不兼容,支持 CI 中执行 docker 命令 | | 自定义 Runner 镜像bun + git + docker CLI | 避免 checkout REST API 不兼容,支持 CI 中执行 docker 命令 |
| Runner 挂载 Docker socket | Job 容器通过 socket 访问宿主机 Docker daemon执行构建操作 | | Runner config 的 `options` + `valid_volumes` | 让 job 容器能挂载宿主机的 `/opt/duoqi-api` 目录,读取 docker-compose.yml |
| CI health check 使用 `bun -e "fetch(...)"` | runner 镜像未安装 curl用 bun 内置 fetch API 做 HTTP 健康检查 |
| 固定 Bun 版本1.3 | 确保 CI 环境可复现,避免 latest 版本变化导致意外失败 | | 固定 Bun 版本1.3 | 确保 CI 环境可复现,避免 latest 版本变化导致意外失败 |
### 部署操作 ### 部署操作
@ -840,11 +849,10 @@ services:
# Phase 2: 多实例 docker-compose.yml # Phase 2: 多实例 docker-compose.yml
# API 服务器上的配置 # API 服务器上的配置
version: '3.8'
services: services:
api: api:
image: your-registry/duoqi-api:latest image: your-registry/duoqi-api:latest
network_mode: host
deploy: deploy:
replicas: 2 # 运行 2 个实例 replicas: 2 # 运行 2 个实例
resources: resources:
@ -1036,6 +1044,48 @@ mysql -h your-rds-endpoint -u duoqi_prod -p -e "SELECT 1;"
# 阿里云 RDS 控制台 → 数据安全性 → 白名单设置 # 阿里云 RDS 控制台 → 数据安全性 → 白名单设置
``` ```
#### 7. Docker bridge 网络与 VPC 内网冲突
> **症状**:服务器无法连接 RDS或 VPC 内其他服务ping 显示源 IP 为 `172.x.0.1`Docker 网桥 IP而非宿主机内网 IP。
```bash
# 查看路由表,检查是否有 Docker 网桥路由劫持了 VPC 流量
route -n
# 如果看到类似以下行,说明 Docker bridge 子网与 RDS IP 段冲突:
# 172.23.0.0 0.0.0.0 255.255.0.0 U 0 0 0 br-xxxxxx
# 查看哪个 Docker 网络创建了冲突子网
docker network ls
docker network inspect <network-name>
# 解决方案 1使用 network_mode: host推荐已在本方案中采用
# 在 docker-compose.yml 中为服务添加 network_mode: host
# 这样不会创建 Docker bridge 网络,从根本上避免 IP 段冲突
# 解决方案 2指定不冲突的子网
# docker network create --subnet=192.168.200.0/24 my-network
```
#### 8. CI health check 失败
```bash
# 检查 health 路径是否正确health 路由注册时无 /v1 前缀)
# 正确:/health 错误:/v1/health
# 检查容器是否在运行
docker ps -a --filter name=duoqi-api-prod
# 检查端口是否在监听host 网络模式下直接看宿主机端口)
ss -tlnp | grep 3000
# 查看容器日志
docker logs duoqi-api-prod --tail 50
# 注意CI health check 使用 bun -e "fetch(...)" 而非 curl
# 如果 bun 的 promise 处理有问题,使用 top-level await
# bun -e "try{const r=await fetch('http://localhost:3000/health');process.exit(r.ok?0:1)}catch{process.exit(1)}"
```
### 回滚操作 ### 回滚操作
```bash ```bash
@ -1113,6 +1163,6 @@ docker compose up -d api-prod
--- ---
**文档版本**: v5.2.0 (双分支工作流 + 国内网络适配 + Docker 执行器完善) **文档版本**: v5.3.0 (host 网络模式 + Act Runner 挂载配置 + 故障排查更新)
**最后更新**: 2026-04-17 **最后更新**: 2026-04-18
**维护者**: Duoqi Team **维护者**: Duoqi Team