部署与发布
项目支持框架依赖发布、自包含跨平台程序包和 Docker 镜像。生产部署前先完成配置参考中的上线检查。
1. 部署前准备
至少准备:
- 生产 MySQL 8.4 数据库及最小权限账号;
- 两项相互独立且至少 32 字符的密钥;
- 强初始管理员密码;
- HTTPS 入口或反向代理;
- 持久化日志收集方式;
- 数据库备份和恢复方案;
- 多实例部署所需 Redis;
- 端口、防火墙和健康检查策略。
生产环境不需要 Node.js 运行服务。Node.js 只在构建 Vue 前端时使用。
2. 本机统一发布
在仓库根目录运行:
pwsh.exe -NoLogo -NoProfile -NonInteractive -File .\scripts\publish.ps1
脚本会:
- 在
ClientApp执行npm ci; - 构建 Vue 生产资源;
- 发布
Eis.Web; - 发布
Eis.Tools。
输出:
artifacts/publish/web
artifacts/publish/tools
启动 Web:
dotnet .\artifacts\publish\web\Eis.Web.dll
查看数据库工具:
dotnet .\artifacts\publish\tools\Eis.Tools.dll --help
这种发布方式需要服务器预装兼容的 .NET 10 Runtime。
3. 发布物目录建议
生产服务器可采用:
eis/
├─ current/ 当前 Web 发布物
├─ tools/ 与当前版本匹配的数据库工具
├─ config/ 由平台管理,不纳入发布压缩包
├─ data/ 仅 SQLite 部署使用
├─ logs/ 若采用文件日志
└─ releases/
├─ 1.2.2/
└─ 1.2.3/
配置和持久化数据不要放进每次覆盖的应用发布目录。升级前保留上一版发布物,以便代码回滚;数据库发生不兼容升级时,还必须配套数据库恢复方案。
4. 自包含跨平台程序包
Gitea Actions 默认构建:
win-x64:.ziplinux-x64:.tar.gzlinux-arm64:.tar.gz
手动选择扩展平台后增加:
win-arm64osx-x64osx-arm64
每个包包含:
eis-<版本>-<RID>/
├─ app/ Web 与数据库工具,共享运行时和依赖
├─ README.md
├─ LICENSE
└─ .env.example
还会生成 SHA256SUMS。
Windows 启动:
.\app\Eis.Web.exe
Windows 数据库工具:
.\app\Eis.Tools.exe --help
Linux/macOS:
./app/Eis.Web
./app/Eis.Tools --help
自包含包不要求目标机预装 .NET Runtime。
5. Docker 镜像
本地构建:
docker build --tag hengzhun-exam-system:local .
镜像:
- 基于 ASP.NET Core 10 Runtime;
- 包含 Web 和
/app/tools/Eis.Tools.dll; - 默认监听
0.0.0.0:4173; - 使用非 root 用户;
- 数据目录
/app/data; - 通过
/health/live健康检查。
Docker Compose
创建配置:
Copy-Item -LiteralPath .\.env.docker.example -Destination .\.env.docker
替换密钥和管理员密码后:
docker compose up --build --detach
docker compose ps
docker compose logs --follow app
默认使用 SQLite,数据库位于命名卷:
exam-information-data:/app/data
停止并保留数据:
docker compose down
删除容器和全部命名卷数据:
docker compose down --volumes
最后一个命令具有破坏性,只在明确清空 SQLite 数据时使用。
6. MySQL 和 Redis 容器部署
使用外部 MySQL 时,以环境变量覆盖 Compose 中的默认 SQLite 配置:
DATABASE_CLIENT=mysql
DATABASE_URL=mysql://...
然后可以移除 SQLite 数据卷挂载,但应先确认没有需要迁移的现有 SQLite 数据。
使用 Redis:
REDIS_URL=redis://redis-host:6379/0
REDIS_SESSION_DB=1
容器中的 127.0.0.1 指向容器自身。MySQL 或 Redis 在其他容器或主机上时,应使用 Compose 服务名、内网 DNS 或实际主机地址。
7. 生产启动顺序
推荐:
- 完成数据库备份。
- 部署新版本到独立目录或拉取新镜像。
- 使用与新版本匹配的工具执行非破坏性数据库预检或初始化。
- 注入生产环境变量。
- 单实例启动新版本。
- 检查
/health/live和/health/migration。 - 检查首页、登录、静态资源和数据库连接。
- 多实例部署时再逐步替换其余实例。
- 完成关键业务烟测。
- 保留上一版本和回滚记录。
若结构版本不匹配,不要继续滚动启动所有实例。
8. 健康检查与监控
存活
GET /health/live
正常响应包含:
{
"status": "healthy",
"service": "Eis.Web",
"framework": ".NET 10"
}
组件状态
GET /health/migration
重点检查:
legacyApiRemoved: truecache.statusauthentication.stateBackend- 原生模块启用状态
cache.status=unavailable 表示普通 Redis 不可用且正在使用本机回退;认证 Redis 如果明确配置却连接失败,应用通常无法完成启动。
监控还应包含:
- HTTP 5xx;
- 登录失败率;
- 数据库连接和慢查询;
- Redis 连接;
- 容器重启次数;
- 磁盘或 SQLite 卷容量;
- 关键批量任务和审批错误。
9. HTTPS 与代理
建议在受管入口、反向代理或负载均衡器终止 TLS,只对外提供 HTTPS。代理配置需要:
- 转发到应用
4173; - 保留必要的 Host 和转发协议头;
- 允许 Excel/PDF 所需响应大小;
- 对 Vue History 路由使用应用自己的回退,不把
/api/*错误改写成首页; - 对登录 Cookie 保持同站点访问模型。
代理和应用的公开域名变化后,检查文书二维码中的验真链接是否指向正确外部地址。
10. Gitea Actions 发布
工作流:
.gitea/workflows/publish.yml
触发方式:
- 推送
v*标签; - Actions 页面手动运行;
- 普通分支推送不会触发耗时发布。
流水线:
- 构建 Vue;
- 运行 Release 配置的 .NET 测试;
- 构建自包含平台包;
- 上传工作流制品;
- 构建
linux/amd64、linux/arm64Docker 镜像; - 推送 Docker Hub 和 Gitea Registry;
- 标签构建创建正式 Release 或 Pre-release。
必要配置
Actions Variables:
DOCKERHUB_IMAGEREGISTRY_USERNAME
Actions Secrets:
DOCKERHUB_USERNAMEDOCKERHUB_TOKENREGISTRY_TOKEN
Release 使用内置 GITEA_TOKEN,仓库或组织的任务令牌最大权限需要允许 Releases Write。
Gitea 镜像当前固定发布到:
git.biss.click/biss/eis-dotnet
Docker Hub 镜像名由 DOCKERHUB_IMAGE 变量决定。
Runner 需要访问:
- Docker daemon;
- GitHub Actions 源;
- Docker Hub;
git.biss.click;- QEMU 注册能力。
11. 版本标签
稳定版本:
git tag v1.2.3
git push origin v1.2.3
会生成语义化镜像标签和 latest。
预发布:
git tag v1.3.0-rc.1
git push origin v1.3.0-rc.1
带连字符的版本会创建 Gitea Pre-release,不覆盖稳定版 latest 或主次版本标签。
发布标签前应确认标签所指提交已经通过本地检查,标签推送后不应移动同名标签来替换已发布制品。
12. 升级与回滚
升级
- 阅读版本变更;
- 备份数据库;
- 保存旧配置和密钥;
- 验证新版本所需环境变量;
- 用隔离数据库或测试环境演练;
- 部署并检查健康状态;
- 执行核心业务烟测。
代码回滚
若数据库结构仍兼容:
- 停止新版本;
- 恢复上一发布目录或镜像标签;
- 使用原有配置启动;
- 检查健康状态和关键业务。
数据回滚
如果新版本已执行不兼容数据库变更,不能只回滚二进制。必须按事先验证的数据库恢复方案恢复匹配版本的数据。
不要通过 database reset 实现生产回滚。
13. 部署后验收
- 首页和公告正常;
- 公开验真页可访问;
- 管理员可登录和退出;
- TOTP 登录可完成;
- 各角色只能看见自己的数据范围;
- Vue 语义 URL 直接刷新正常;
- Excel 模板可下载;
- PDF 文书可生成并验真;
- 数据写入后公开和成绩缓存及时失效;
- 数据库备份任务正常;
- 监控能发现进程、数据库和 Redis 故障。