Files
yms-daemon/RUNBOOK_CONTAINER_BACKEND.md
2026-08-17 10:10:14 +08:00

3.9 KiB

Container backend 运行手册

本文只描述已经实现的 Docker standalone backend 更新路径。开发环境通过 Registry pull 获取镜像;客户离线环境的 repack ZIP load 尚未接入 CLI。

1. daemon 配置

/etc/yms-daemon/yms-daemon.toml 使用以下精确内容。systemctl_path 仅用于 native backend systemd 操作;本地 Nginx 切流固定使用 /usr/sbin/nginx -s reload

[daemon]
environment = "dev"

[backend]
type = "container"
systemctl_path = "/bin/systemctl"

[backend.slot.8080]
container_name = "backend-8080"
health_endpoint = "http://127.0.0.1:8080/yms/actuator/health"

[backend.slot.8081]
container_name = "backend-8081"
health_endpoint = "http://127.0.0.1:8081/yms/actuator/health"

2. 固定运行参数

daemon 创建 backend 容器时固定使用:

  • --network host
  • root 用户 0:0
  • restart policy no
  • SERVER_PORT=8080SERVER_PORT=8081
  • SPRING_CONFIG_LOCATION=file:/app/config/yms.yaml
  • /home/yms/conf/yms.yaml:/app/config/yms.yaml:ro
  • /home/yms/tmp:/home/yms/tmp
  • 容器 graceful stop 上限 9000 秒,与 Spring Boot 的 150m graceful shutdown 配置对齐

启动 daemon 前,以下路径必须已经存在:

/home/yms/conf/yms.yaml
/home/yms/tmp

yms.yaml 必须是普通文件;/home/yms/tmp 必须是非符号链接目录。SPRING_CONFIG_LOCATION 会替换 Spring Boot 的默认配置搜索位置,因此该文件必须同时包含 Spring Boot 配置和原 config 文件中的业务配置,不再依赖 JAR 内配置文件追加合并。

3. 已有 container 部署的更新

host Nginx 当前指向 8080 时,backend-8080 必须正在运行;当前指向 8081 时,backend-8081 必须正在运行。daemon 会拒绝容器名、端口和 Nginx 状态无法对齐的更新。

测试命令:

ymsctl update \
  --service backend \
  --container-image harbor.ymswell.asia/ymswell/glory-ymswell:20260813-184902-a37bf50d-v1.1.8.1

daemon 执行以下事务:

  1. pull 完整 tag 引用。
  2. 读取与仓库名精确匹配的 RepoDigest,并将后续步骤固定到 repository@sha256:...
  3. 删除非活动 slot 上次留下的已停止容器。
  4. 创建并启动非活动 slot。
  5. 最长等待 120 秒,检查 /yms/actuator/health 的顶层 statusUP
  6. 原子更新 host Nginx 配置并 reload。
  7. 排空旧 slot,随后 graceful stop 旧容器。
  8. 提交事务;旧容器保留为 stopped 状态,下次该 slot 被使用时删除。

4. 全新机器首次部署

同一条 update --container-image 命令可以完成全新机器的首次部署,但必须同时满足以下事实:

  • SQLite 中不存在已提交的 container backend 部署记录。
  • SQLite 中不存在历史 COMMITTED container backend 事务。
  • backend-8080backend-8081 均不存在。

daemon 以 Nginx 当前活动端口为基准,选择当前未接流的槽位,完成容器创建、启动和健康检查后再切换 Nginx。首次部署没有旧容器,因此不会等待 drain,也不会执行停止旧容器;事务提交时会在同一个 SQLite 写事务内记录活动端口、容器名、镜像 digest、容器 ID 和事务 ID。

如果 SQLite 已存在部署记录或历史 COMMITTED container backend 事务,而现场容器缺失,daemon 按状态漂移拒绝更新。daemon 不会用“两槽容器均不存在”这一项单独推断全新机器。FAILEDROLLED_BACK 首装事务不代表机器曾成功部署;再次人工执行同一更新命令时,daemon 会恢复未完成的回滚。回滚到 ROLLED_BACK 后再次执行命令,daemon 会清理已停止的目标容器并创建新事务,允许使用同一镜像重新部署。

5. native 到 container 的边界

普通 update --container-image 不会把 native systemd backend 自动识别成 container。native 到 container 必须进入独立迁移事务;该迁移执行器尚未实现。不得通过修改 backend.type 绕过迁移事务。