Skip to content

部署与运维 ​

更新:2026-10-31。本文面向使用阿里云 ACR 镜像和仓库内 deploy/compose.yml 的运维人员;命令均在服务器的仓库 deploy/ 目录执行。配置与脚本以仓库中的 deploy/README.md 为准。

部署构成 ​

源码目录Compose 服务 / 镜像宿主机端口说明
—mysql / mysql:8.03308 → 3306数据在 mysql-data 卷;应用账号 weiran,数据库 weiran4j
packages/server/backend / kecheng-backend不直接映射Spring Boot 在容器内监听 5200,启动时执行 Flyway
packages/manage/web / kecheng-web5202 → 80Nginx 提供后台页面,并同源代理 /api-backend/
packages/web/site / kecheng-site5204 → 3000Next.js 用户端;构建时将 /api-backend/ 指向 Compose 的 backend:5200

这三个应用镜像由 .github/workflows/docker-images.yml 构建,推送到 kjs-dw-mogu-registry.cn-hangzhou.cr.aliyuncs.com/imvkmark/ 命名空间,名称分别为 kecheng-backend、kecheng-web、kecheng-site。docs/ 的 VitePress 站点目前只提供本地开发和静态构建,不在 Compose 中运行;本地用 pnpm dev:docs 访问 5409 端口。

源码目录已归入 packages/;Compose 服务名与镜像名保持不变,以兼容当前部署脚本和容器间地址。

发布镜像 ​

向仓库推送 v*.*.* 标签,或在 GitHub Actions 中手动运行 Publish Aliyun images 并填写版本号。工作流构建 linux/amd64 镜像,同时推送去掉 v 的版本标签及 latest。工作流需要 ACR_USERNAME、ACR_PASSWORD;后端构建使用默认 GITHUB_TOKEN 读取 weiran-tech/weiran4j GitHub Packages,两个前端镜像构建时 pnpm 还需读取 @weiran-tech/backend-components 的元数据,因此必须设置具有该包读取权限的仓库 Secret WEIRAN_PACKAGES_TOKEN。本地安装和手动构建镜像的令牌配置见 deploy/README.md。

部署脚本使用 Compose 文件中写死的 latest。发布完成后,先确认三个镜像都已成功推送,再运行部署脚本,避免部署混合版本。需要固定版本或回退时,先把 Compose 中三个应用镜像改为同一个已发布版本;deploy.sh 不接受镜像版本参数。

首次部署 ​

服务器需要 Docker Engine、Docker Compose 插件和访问 ACR 的网络。对公网提供服务时应准备 HTTPS 入口;仅在受控网络中使用 HTTP 时,按下文的 HTTP 配置调整。将仓库中的 deploy/ 目录放到服务器后执行:

sh
cd deploy
cp .env.example .env
chmod 600 .env
mkdir -p secrets
(umask 077; openssl rand -base64 48 > secrets/mysql-root-password)

编辑 .env,至少设置以下值:

变量用途
WEIRAN_DB_URL内置 MySQL 使用 jdbc:mysql://mysql:3306/weiran4j?...;外部数据库填实际 JDBC 地址
WEIRAN_DB_USERNAME / WEIRAN_DB_PASSWORD内置 MySQL 使用 weiran 和应用账号密码;密码同时用于初始化内置 MySQL
WEIRAN_JWT_SECRET至少 32 字节;可用 openssl rand -base64 48 生成
WEIRAN_PUBLIC_BASE_URL后台对外地址,协议、域名和非默认端口必须与实际访问地址一致,不带末尾斜杠;用于外部身份回调等链接
WEIRAN_COOKIE_SECUREHTTPS 环境设为 true;纯 HTTP 环境必须设为 false,否则浏览器不会保存认证 Cookie
WEIRAN_WEB_PORT / WEIRAN_SITE_PORT可选,默认 5202 / 5204

deploy/.env.example 是 Compose 的实际模板。packages/server/.env.example 是后端独立运行时的完整变量清单,不能直接替代前者。两个文件中的真实密钥都不应提交到仓库。

sh
docker login kjs-dw-mogu-registry.cn-hangzhou.cr.aliyuncs.com
./deploy.sh

脚本先校验 Compose 配置,再拉取镜像、启动容器并等待后端健康。内置 MySQL 首次启动时创建 weiran4j 数据库和 weiran 用户;后端随后执行 Flyway。数据库数据和后端日志分别保存在 mysql-data、backend-logs 卷,容器重建不会删除卷。

网络与 HTTPS ​

Compose 自身不提供 TLS。宿主机 Nginx 示例在 deploy/nginx.example.conf,按两个域名映射:admin.example.com → 127.0.0.1:5202(后台),study.example.com → 127.0.0.1:5204(用户端)。将示例中的域名和证书路径替换为实际值后放入宿主机 Nginx 的配置目录,用 nginx -t 检查再重载。示例假定 Nginx 与 Compose 在同一台主机;若不在同一台,需将上游地址改为可达的宿主机地址。

外层代理把整个路径转给对应容器,/api-backend/ 因而保留为同源路径:后台容器的 Nginx 再转发给 backend:5200;用户端由 Next.js rewrite 转发。代理需透传 Cookie、Set-Cookie、X-CSRF-Token、X-Forwarded-Proto 和请求号;后台容器会继续传递外层的 HTTPS 协议头。WEIRAN_PUBLIC_BASE_URL 应填实际后台域名,例如 https://admin.example.com。WEIRAN_COOKIE_SECURE=true 时,直接用 HTTP 访问会导致浏览器不保存认证 Cookie。

MySQL 的 3308 端口由 Compose 映射到宿主机,须按实际运维访问范围配置服务器防火墙。外部数据库部署可以保留现有 WEIRAN_DB_URL,但当前 Compose 仍会启动内置 MySQL,backend 也仍需等待它健康;不能仅修改 JDBC 地址就移除内置数据库服务。

仅使用 HTTP ​

没有 HTTPS 时,deploy/.env 中至少调整这两项。域名替换为实际后台域名;如果通过 :5202 直接访问,地址也应包含 :5202:

dotenv
WEIRAN_PUBLIC_BASE_URL=http://admin.example.com
WEIRAN_COOKIE_SECURE=false

外层 Nginx 应使用监听 80 的普通代理站点,将后台域名转到 127.0.0.1:5202、用户端域名转到 127.0.0.1:5204;不要使用 deploy/nginx.example.conf 中的 HTTP→HTTPS 跳转和证书配置。两个站点都要保留 /api-backend/ 同源路径,不能让页面从另一个域名直连后端。更新 .env 后重建后端容器使变量生效。WEIRAN_JWT_SECRET、数据库密码和 SPRING_PROFILES_ACTIVE=prod 的要求不因使用 HTTP 而改变;镜像构建时的 WEIRAN_API_ORIGIN=http://backend:5200 是容器内地址,也无需改成公网域名。

HTTP 会以明文传输登录密码和认证 Cookie,只适合受控网络或短期验收。将来启用 HTTPS 时,需要把 WEIRAN_PUBLIC_BASE_URL 改为 https://...,并把 WEIRAN_COOKIE_SECURE 改回 true。

升级与核验 ​

升级前确认实际使用的是内置还是外部数据库,并备份实际使用的数据库。内置 MySQL 可在 deploy/ 中执行以下命令;先准备好只有管理员可写的备份目录:

sh
umask 077
BACKUP_FILE=/secure/backups/kecheng-$(date +%Y%m%d-%H%M%S).sql
docker compose --env-file .env -f compose.yml exec -T mysql sh -c \
  'MYSQL_PWD="$MYSQL_PASSWORD" mysqldump --single-transaction --no-tablespaces --set-gtid-purged=OFF --routines --triggers --events -u "$MYSQL_USER" "$MYSQL_DATABASE"' \
  > "$BACKUP_FILE"
test -s "$BACKUP_FILE"

外部数据库按其自身备份流程操作。确认新版本三个镜像均已发布、备份可用后运行 ./deploy.sh。部署完成后核对:

sh
docker compose --env-file .env -f compose.yml ps
docker compose --env-file .env -f compose.yml logs --tail=100 backend
curl -fsS http://127.0.0.1:5202/ >/dev/null
curl -fsS http://127.0.0.1:5204/ >/dev/null

若修改了 WEIRAN_WEB_PORT 或 WEIRAN_SITE_PORT,相应替换检查端口。再通过实际对外地址验证后台和用户端登录,以及云学院课程、考试等关键页面。后端健康检查使用容器内的 /api-backend/n/health。Flyway 状态记录在 sys_migration;有历史教育账号的数据库升级到 edu_user 前,还应检查 迁移设计 中的登录名、手机号和角色冲突。

回退与故障处理 ​

deploy.sh 只会拉取当前 Compose 指定的镜像并等待后端健康,不会回退数据库。若新版本已执行 Flyway,回退应用时必须同时恢复与旧版本匹配的升级前数据库备份;仅把镜像改回旧版本无法撤销表结构和数据迁移。恢复前先停止写入,保留故障现场日志,再恢复数据库、把三个应用镜像固定到同一旧版本并重启。恢复过程按实际数据库的备份方案执行,避免在后端仍运行时导入备份。

现象检查项
deploy.sh 提示配置缺失检查 deploy/.env、secrets/mysql-root-password 和 docker compose --env-file .env -f compose.yml config
后端长期不健康查看 docker compose --env-file .env -f compose.yml logs backend mysql;重点检查 JDBC 地址、密码、MySQL 健康状态和 Flyway 错误
登录后立即退出检查实际访问协议与 WEIRAN_COOKIE_SECURE 是否匹配、代理是否透传 Cookie 和同源 /api-backend/
后台或用户端 API 失败检查 packages/manage/nginx.conf 代理、packages/web/next.config.ts 构建时的 WEIRAN_API_ORIGIN,以及后端容器健康状态
课程文件或系统上传失败课程附件存于业务数据库;系统文件上传还取决于 WEIRAN_STORAGE_MODE,默认 disabled,启用 OSS 时需要相应 WEIRAN_STORAGE_ALIYUN_* 配置