# 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`。 ```toml [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=8080` 或 `SERVER_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 前,以下路径必须已经存在: ```text /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 状态无法对齐的更新。 测试命令: ```bash 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` 的顶层 `status` 为 `UP`。 6. 原子更新 host Nginx 配置并 reload。 7. 排空旧 slot,随后 graceful stop 旧容器。 8. 提交事务;旧容器保留为 stopped 状态,下次该 slot 被使用时删除。 ## 4. 全新机器首次部署 同一条 `update --container-image` 命令可以完成全新机器的首次部署,但必须同时满足以下事实: - SQLite 中不存在已提交的 container backend 部署记录。 - SQLite 中不存在历史 `COMMITTED` container backend 事务。 - `backend-8080` 和 `backend-8081` 均不存在。 daemon 以 Nginx 当前活动端口为基准,选择当前未接流的槽位,完成容器创建、启动和健康检查后再切换 Nginx。首次部署没有旧容器,因此不会等待 drain,也不会执行停止旧容器;事务提交时会在同一个 SQLite 写事务内记录活动端口、容器名、镜像 digest、容器 ID 和事务 ID。 如果 SQLite 已存在部署记录或历史 `COMMITTED` container backend 事务,而现场容器缺失,daemon 按状态漂移拒绝更新。daemon 不会用“两槽容器均不存在”这一项单独推断全新机器。`FAILED`、`ROLLED_BACK` 首装事务不代表机器曾成功部署;再次人工执行同一更新命令时,daemon 会恢复未完成的回滚。回滚到 `ROLLED_BACK` 后再次执行命令,daemon 会清理已停止的目标容器并创建新事务,允许使用同一镜像重新部署。 ## 5. native 到 container 的边界 普通 `update --container-image` 不会把 native systemd backend 自动识别成 container。native 到 container 必须进入独立迁移事务;该迁移执行器尚未实现。不得通过修改 `backend.type` 绕过迁移事务。