6.0 KiB
ADR-0198:绑定 Digest 的本机 Compose Rollout Preflight
- 状态:Accepted(只读 preflight 已实现;真实 apply/健康处置见 ADR-0199)
- 日期:2026-07-29
- 关联 RFC:QL-RFC-0001 D-184、D-185、D-186、D-187、D-188
- 关联 ADR:ADR-0194、ADR-0195、ADR-0196、ADR-0197
背景
ADR-0197 已把 desired image 切换收敛为 generation CAS,但“某个 digest 已签名”和 “该 image 能安全打开当前 deployment”是两种不同事实。旧 image 可能只支持较早 SQLite capability;本机 tag/image ID 可能没有 registry identity;Compose 两个文件 也可能被错误顺序、错误 project 或错误 daemon 解释。
原 Compose descriptor 未声明 project name。Compose 默认从配置目录名派生 project,
所有标准 deployment 都位于名为 service 的目录,因此同一 Docker daemon 上的多个
QingLong 实例可能共享 project identity。
在没有这些事实时直接实现自动 up 或自动 rollback,会把镜像供应链、Docker
副作用、SQLite migration 和健康判断错误地包装成一个不存在的事务。
决策
1. Image config 声明可审计兼容窗口
AI-excluded local image 固定增加:
io.qinglong.local.application-config=2
io.qinglong.local.compose-selection=1
io.qinglong.local.sqlite-contract-min=35
io.qinglong.local.sqlite-contract-max=35
同时保留并复核 io.qinglong.profile=edge,standalone、
io.qinglong.ai=excluded、OCI source/revision/version、numeric
65532:65532 和唯一 entrypoint。min/max 是该 image 可打开的 SQLite contract
闭区间,不是“最新版本”提示;当前 image 只接受 exact v35。
这些 label 同时进入:
- Dockerfile 静态 mutation audit;
- native amd64/arm64 image inspect;
- OCI layout 双平台 config exact audit;
- pushed digest 的 release preflight。
调用方 command 中不得复制或声明这些 label。preflight 只信 Docker daemon 对 exact RepoDigest 返回的 image config。
2. Project 与容器 revision 身份稳定
基础 compose.yaml 的 top-level name 从 instance ID 生成:
ql3-<bounded-slug>-<domain-separated-sha256-prefix>
. 会转为 -,摘要关闭 slug 碰撞。名称不依赖 deployment root,目录移动不会静默
创建第二个 project;重复 instance ID 也不会在同一 daemon 上被当作两个实例。
compose.image.yaml 除 exact image 外,向 qinglong3 service 写入:
io.qinglong.deployment.generation
io.qinglong.deployment.mutation
两者由 canonical selection 重复派生并在解析时交叉复核,不能由 operator 单独填写。 后续 apply/recovery 可据此识别 container 对应的 durable desired revision。
3. Preflight 是现有短生命周期 CLI 的只读操作
入口继续复用现有 package 和 binary:
ql3-local-deploy compose-preflight \
--command-file /absolute/private-command.json
command 只含 deployment root、canonical Docker executable、canonical Unix socket、 root acknowledgement 和 expected generation。Docker executable 必须是 root 或当前 UID 拥有、不可 group/world write 的 canonical regular executable。socket 必须是 root 或当前 UID 拥有、非 symlink、非 world-writable 的 canonical Unix socket。 CLI 不使用 ambient Docker context。
检查顺序:
- 复核 deployment/service/revision 目录与 active/archive exact;
- 从 application v2 读取 instance/Profile/busy timeout,再用正式 renderer 重建并 byte-exact 复核 application config 与 Compose descriptor;
- 对 host SQLite 执行完整 read-only readiness:quick/foreign-key check、70 条 migration history、schema、Plugin Package evidence 与 contract v35;
- 以显式
--host unix://...和一次性0700空 Docker config 执行image inspect;要求本地 RepoDigests 包含 active exact reference,并复核 OS/arch/user/entrypoint/source/revision/version/Profile/AI 与 compatibility labels; - 对 base + selection 执行真实
docker compose config --format json,精确复核 project、image、generation/mutation label、UID:GID、read-only root、network none、drop ALL、no-new-privileges、memory/PID、command、唯一 bind 和 tmpfs。
成功输出仅含 ready、generation、Profile、SQLite contract、architecture 和 service kind,不输出 root、socket、executable、image/digest 或 mutation。
4. Preflight 不执行 rollout
本命令不得:
- pull/build/push image;
- create/start/stop/restart/remove container;
- 打开可写 SQLite、执行 migration 或创建 backup;
- 写 deployment receipt、修改 selection 或自动 rollback;
- 把本地 registry evidence 宣称为正式 release。
正式 operator 仍须先完成 D-186 signature/attestation verify 和显式 pull,再运行本 门。共享 release workflow 对 local pushed digest 的只读检查已由 ADR-0199 的 Edge 与 Standalone 真实 rollout gate 包含并加强。
验收
- application config v2、selection v1、SQLite
35..35四项 label 在 Dockerfile/native image/OCI layout/release workflow 中锁定; - Compose project name 对 instance 稳定,selection label 与 generation/mutation exact;
- stale generation、active/archive/config/descriptor drift、非 socket、错误 RepoDigest、标签窗口或 Compose 合并均拒绝;
- 完整真实 SQLite v35 readiness 在 Docker 之前执行;
- CLI 输出低敏且不产生 Docker container 副作用;
local-owner-cli36/36、镜像/OCI/release 专项 36/36;- arm64 Docker Compose v5.3.1 对 Edge/Standalone 的 localhost exact manifest live preflight 均 compatible;
- workspace 保持 22 packages,无新增生产依赖。
未包含
docker compose up、active event、receipt 与失败 rollback(由 ADR-0199 实现);- SQLite migration 前 backup、写后 capability 识别和旧 image compatibility;
- systemd/OpenRC 制品 compatibility/preflight;
- 正式 GHCR 双架构 workflow 成功记录和物理路由设备门。