KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
资料与课程依据 — keel 龙骨
私有化交付工程:把一套系统送进客户内网 的参考信息:资料与课程依据
这份文档的用途
本课的每一处机制结论都要能追到一个规范条文或官方文档;追不到的,正文会写明
「这是本课的设计说明」,不写成产品要求。这份文档是那张对照表的落点,同时交代证据口径——
正文里出现的读数来自哪套环境、哪些数字随环境变、哪些是刻意伪造的演练材料。
三类依据要分开看,正文里也是分开写的:
| 类别 | 含义 | 正文里的写法 |
|---|---|---|
| 规范 / 官方文档规定 | 上游文档写死的行为或语义 | 写「按 Compose 规范……」并给出条款出处 |
| 常见实现 | 文档没写死、但主流实现默认这么做(本课主体是 Docker Engine 29.8.2 + Compose v2) | 写「默认行为是……」,并说明它不属于规范要求 |
| 本课设计 | 为了讲清楚而选的教学形态(最小系统、刻意的缺陷、演练用的坏版本) | 写「本课这样做,真实交付要换」 |
第三类不冒充前两类。最典型的例子有两处:
board:1.0.0里那个「被SIGKILL的任务永远停在running」的缺陷是刻意保留的,
它用来让「停机窗口」这一条有可复现的后果;1.1.0修掉它,于是又有了一条真实的升级链。board:1.2.0是故意做坏的(第 4 版迁移引用了一个不存在的列),它只用于演练
「升级失败自动回滚」,不是任何版本的正常形态。
证据环境与口径
- 正文里的编排解析读数、容器状态读数与日志行,来自 Docker Engine 29.8.2 + Docker Compose v2
这套环境;宿主 Docker 跑在 Linux 容器语义下(stop_grace_period、SIGTERM、internal网络
都是容器语义,不是宿主操作系统的进程语义)。 - 被交付物是
board的两个版本:1.0.0与1.1.0,另有一个只用于演练的坏版本1.2.0。1.0.0与1.1.0的差别是:迁移 3 加了tasks.claimed_at,worker 启动时先回收孤儿任务,
并新增配置BOARD_ORPHAN_AFTER_SECONDS(默认120)。 - 基础镜像是
python:3.12-slim,数据库镜像是postgres:16-alpine,Python 依赖是psycopg[binary]==3.2.9。 这几项固定,正文引用的尺寸读数才有参照。 - 读形状,别背数字。 磁盘可用量、命令耗时、容器 id、现场随机生成的数据库密码、
归一化后的字节串,全都随环境变。正文引用它们是为了让你看到值与关系,不是让你抄。 - 本课的证据只来自这套
board交付链。 其它课程有各自的实验环境与版本,不要把版本号
互相当依据引用——同名概念的语义在不同层级里可能完全相反(见glossary.md末尾的分界那条)。
出处清单
| 依据 | 出处 URL | 检索日期 | 本课用在哪 |
|---|---|---|---|
Docker Engine 命令行参考(docker image save / load / inspect、docker network inspect) |
https://docs.docker.com/reference/cli/docker/ | 2026-10-15 | 02、03、05 章 |
Docker 容器停止与信号语义(docker stop 的宽限期、SIGTERM 之后才是 SIGKILL) |
https://docs.docker.com/reference/cli/docker/container/stop/ | 2026-10-15 | 06 章 |
Compose 规范:name(项目名前缀) |
https://docs.docker.com/reference/compose-file/version-and-name/ | 2026-10-15 | 05 章 |
Compose 规范:服务的 command / entrypoint 与 exec / shell 两种形式 |
https://docs.docker.com/reference/compose-file/services/ | 2026-10-15 | 02、05 章 |
Compose 规范:depends_on 的 service_healthy 与 service_completed_successfully |
https://docs.docker.com/reference/compose-file/services/#depends_on | 2026-10-15 | 04 章 |
Compose 规范:stop_grace_period(发 SIGKILL 之前等待的时长,默认 10 秒) |
https://docs.docker.com/reference/compose-file/services/#stop_grace_period | 2026-10-15 | 06 章 |
Compose 规范:deploy.resources.limits(Swarm 语法,Compose 只翻译子集) |
https://docs.docker.com/reference/compose-file/deploy/ | 2026-10-15 | 05 章 |
Compose 规范:healthcheck(探针住在编排里,而不是镜像里) |
https://docs.docker.com/reference/compose-file/services/#healthcheck | 2026-10-15 | 02、04、07 章 |
Compose 命令行参考(config --variables / --services / --format、ls -q) |
https://docs.docker.com/reference/cli/docker/compose/ | 2026-10-15 | 04、05、07 章 |
Docker 网络驱动与 internal 网络(没有通往宿主机的出口) |
https://docs.docker.com/engine/network/drivers/bridge/ | 2026-10-15 | 03、07 章 |
Dockerfile 参考(USER、CMD 的 exec 形式、多阶段构建) |
https://docs.docker.com/reference/dockerfile/ | 2026-10-15 | 02 章 |
PostgreSQL 官方镜像文档(POSTGRES_* 环境变量与 pg_isready) |
https://hub.docker.com/_/postgres | 2026-10-15 | 04、07 章 |
pg_dump / psql 官方文档(备份与恢复的用法) |
https://www.postgresql.org/docs/16/app-pgdump.html | 2026-10-15 | 06 章 |
psycopg 3 文档(连接串关键字形式、autocommit、异常类型) |
https://www.psycopg.org/psycopg3/docs/ | 2026-10-15 | 04、06、07 章 |
GNU coreutils 的 sha256sum -c(清单校验的语义与失败输出) |
https://www.gnu.org/software/coreutils/manual/html_node/sha2-utilities.html | 2026-10-15 | 01、04 章 |
上表列的是规范与官方文档。正文里的运行读数(尺寸、耗时、日志行、报错原文)来自这套 board
交付链的实际运行记录,环境与版本见上一节;那些数字随环境变化,正文引用它们只为呈现位置与关系。
规范规定 vs 常见实现:三处最容易混的地方
stop_grace_period的默认值是多少? Compose 规范给的默认是 10 秒(SIGTERM之后等这么久
才SIGKILL)。本课把worker设成60s、web设成15s、db设成30s——这三个值都不是规范要求,
而是本课按「手上活最长要跑多久」算出来的。把它当成「应该照抄的配置」是本末倒置:
它是现场参数,取值必须由任务耗时决定。deploy.resources.limits在单机 compose 里生效吗? 这个字段的来源是 Swarm 的部署语法,
Compose 只翻译它的一个子集。本课的观察是:解析输出里只看到deploy.resources.limits.memory、mem_limit字段没有出现,而运行中的容器确实拿到了内存与 CPU 限制。
这说明「声明了什么」与「什么生效了」之间隔着一层翻译,要判断实际生效值,只能看运行中的容器。internal: true等于「访问会被拦截」吗? 规范与官方文档的语义是这个网络没有通往外部的路由。
本课的可观察形态正是这条:出网失败报的是内核级的Network is unreachable,不是超时。
把两者混起来,会导致排障方向相反——「超时」要去查网络策略,而「没有路由」要先查网络拓扑。
关于「一个镜像多种角色」这件事的归属
本课反复强调:探针、启动命令、停机窗口住在编排文件里,不住在镜像里。
这条判断有官方文档支撑(healthcheck 与 command 都是服务级字段),但它的理由是本课的:
一个镜像要扮演 web / worker / migrate / config / doctor 五种角色,
五种角色对「健康」与「停得干净」的定义完全不同,把其中之一写死在镜像里,等于让 worker 去回答 web 的问题。
这是本课设计,不是规范要求。规范允许你把 HEALTHCHECK 写进镜像;
只是在内网交付这个形态里,那样做会制造现场事故。
术语口径
本课用到的术语在 glossary.md 里给了本课程口径的工作定义;上游文档的严格定义以上表出处为准。
两边冲突时,以上表为准,并在正文里说明差异。