KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

私有化交付工程:从「在我机器上是好的」到客户能自己收场 — keel 龙骨

私有化交付工程:把一套系统送进客户内网 的参考信息:私有化交付工程:从「在我机器上是好的」到客户能自己收场

7 章 · 每一章都建立在一套可运行的交付包与一条真实的升级链上

交付最难的一刻,不是把系统做出来的时候,而是它在一个你进不去的地方不工作时。

「明明在我机器上是好的」——这句话在私有化交付里不是一句抱怨,它是一个结构性事实:
你依赖的那些东西(镜像能从仓库拉、依赖能在线装、日志有人自动收、出事能立刻登上去看)
在客户机房里一样都不在。所有的设计问题都是从这句话倒推出来的。

这门课从一条真实的交付链出发:把一套最小系统打成一个自带全部输入的包,
搬进一个没有出口的机房,按固定顺序落地,然后升级、回滚、排障。
每一条约束都配一次故意破坏——把停机窗口改小、把迁移写坏、把数据库停掉、把镜像漏掉——
看它从哪里断、断的时候现场留下了什么。

三个现场

现场一:包搬过去了,起不来,报的却是「网络问题」。

镜像没从包里导进来,docker compose up 的默认行为会去仓库取。客户内网没有出口,
于是屏幕上先出现 Pulling,然后是几十秒的等待,最后落到一句 failed to resolve reference。
看起来像网络不稳,真相是制品根本没进来——而这段等待把最贵的东西耗掉了:现场那几分钟。

现场二:升级「成功」了,但任务永远停在处理中。

worker 手上一个任务要跑二十秒,而停机窗口被设成了五秒。docker stop 等到窗口用完就 SIGKILL,
任务被砍在中间——不报错、不留痕,只留下一行永远停在 running 的数据,
而且重启 worker 也不会收拾它,因为新 worker 只领 pending。

现场三:回滚命令跑了,退出码 0,什么都没发生。

用旧镜像去退结构,而旧镜像的迁移表里根本没有新那一版——于是 --to N 变成一次静默的空操作。
命令成功、退出码 0、库还在新结构上,然后起栈时探针喊「库结构版本对不上」。
这一条的教训比它本身值钱:退出码为 0 不等于它做了你以为的那件事。

这门课回答什么

你可能正在纠结的问题 在哪一章
私有化和普通部署到底差在哪几段? 01
一个能送进内网的镜像里装了什么?为什么代码很小、镜像很大? 02
没有外网怎么把制品搬进去?「能拉」为什么不能假设? 03
从压缩包到跑起来隔着几步?哪一步失败会留下半成品? 04
一套代码怎么给多个客户在同一台机器上各起一套? 05
停机窗口该设多少?为什么任务会永远停在处理中? 06
升级怎么做到「要么升上去、要么原样退回来」?回滚为什么最容易写错? 06
客户说「不对」的时候,他先能自己查出什么? 07
这套形态明确不解决什么? 07

这门课不回答什么

章节地图

01 为什么私有化交付不一样 ─────────────  先站到高处:这条链路和普通部署差在哪
        │
        ▼
02 一个自足的镜像 ────────────────  要搬的到底是什么,为什么这么重
        │
        ▼
03 没有外网怎么把制品搬进去 ───────  跨过一段没有网络的路
        │
        ▼
04 从压缩包到跑起来 ──────────────  现场五步,顺序错了会留下什么
        │
        ▼
05 配置注入与多实例 ──────────────  同一份镜像怎么给多个客户各起一套
        │
        ▼
06 升级与回滚 ───────────────────  怎么让结局只有两种
        │
        ▼
07 现场排障与边界 ───────────────  把能自己查的交出去,并说清不做什么

七章的分工是**「先拆链路、再看制品、再搬、再落地、再并存、再演进、最后收口」**:
01 划清与普通部署的界线,02–03 把「要搬的东西」和「怎么搬」讲透,
04–05 讲现场的落地与多客户并存,06 集中处理可逆性,07 收在排障与边界上。

配套项目

course/project/ 是一套只用标准库的最小系统加一整套交付脚本:

app/board/               七个源文件:config / log / db / web / worker / __main__
Dockerfile               多阶段、非 root、刻意不带 HEALTHCHECK
deploy/self-hosted/      compose.yml + env.example + install / upgrade / rollback / selfcheck
deploy/build-bundle.sh   打离线包(跑在有外网的那一侧)
deploy/variants/         初版 1.0.0 的差异文件(让 06 章的升级演练有真实的起点)

它不替代任何真实产品,只做一件事:把「交付链路上到底发生了什么」变成可读、可改、可破坏的代码与脚本。
五个角色(web / worker / migrate / config / doctor)共用同一个镜像,
靠启动命令区分——这一个决定就带出了本课三分之一的判断。

学完以后你能做什么

关于证据口径


课程导读(起点自检、章节地图、主案例、前置要求)见 course/README.md。

进入 keel 阅读