KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
00 · 交付包 — keel 龙骨
类型:主题概念 · 应用课对应:01 章 · 为什么「私有化」不是「多买一台服务器」
类型:主题概念 · 应用课对应:01 章 · 为什么「私有化」不是「多买一台服务器」
这一页只回答四件事:它为什么会出现、它是什么、它长什么样、它怎么工作。它不讲怎么安装,也不讲怎么升级。
一、它为什么会出现
一次交付的两头差别很大。我们这边能构建、能从公共仓库取基础镜像、网络抖一下还能重试;客户那边是一台到不了外面的机器,中间只隔着一条能搬东西的通道。
现场的形状是这样的:
我们这边:能 docker build、能从仓库取基础镜像、失败能重试一次
搬运途中:只有 U 盘 / 摆渡机 / 刻录介质,没有人能"顺手看一眼"
客户那边:能做的事只有 docker load,装什么必须已经在手里
需求一句话:把「这次安装需要的全部输入」和「证明它们没在搬运途中坏掉」,装成一份能整体搬动的东西。
它要解决的不是"怎么把文件传过去",而是怎么让对面在没有人陪的情况下,只靠手里这一份东西把系统装起来。
二、它是什么
一句话:交付包 = 一次安装所需的全部输入 + 一份完整性证明,被打成一个可以整体搬运的目录。
四个名字先分清,后面几页都会用到:
| 名字 | 它指什么 |
|---|---|
board-delivery-1.0.0/ |
交付包本身 |
board-delivery-1.0.0.tar.gz |
它在搬运通道上的形态,160M |
images/board__1.0.0.tar |
包内最重的一件制品(未压缩) |
MANIFEST.sha256 |
那份完整性证明 |
它不是下面这三样东西——混淆了就会做错取舍:
- 不是一个"压缩包"。 压缩只服务于搬运;解开它,里面是一个有分工的目录,不是一堆散文件。
- 不是"源码加文档"。 源码在包里只有 61.4kB,包里的重量几乎全在运行环境上。
- 不是"镜像的别名"。 镜像只是包内最重的一件制品,包里还有编排文件、配置模板、四个脚本和一份哈希清单——少任何一样,对面都装不起来。
三、它长什么样
它长成一个目录,顶层每一行都有职责:
board-delivery-1.0.0/
MANIFEST.sha256 每个制品的哈希
images/
board__1.0.0.tar 应用镜像(docker save 直出,未压缩)
postgres__16-alpine.tar 数据库镜像 —— 别漏了这个
compose.yml 客户内网版编排文件,被直接使用的那一份
env.example 配置模板;真的 .env 由安装脚本照它现场生成
install.sh 客户唯一需要知道的那条命令
upgrade.sh rollback.sh selfcheck.sh
它由两条 docker save 加一句 tar -czf 做出来,两条都不能省:
docker save --output "images/board__${VERSION}.tar" "${APP_IMAGE}"
docker save --output "images/postgres__${DB_IMAGE##*:}.tar" "${DB_IMAGE}"
应用镜像准备得再完整,客户机器上没有 postgres,编排一样会去仓库取,然后在没有出口的网络里挂到超时。
体积读数放在一起看,重量在哪就一目了然:
基础镜像 python:3.12-slim 179MB
应用镜像 board:1.0.0 215MB
其中:依赖层(一个 venv) 28.2MB
其中:应用代码层 61.4kB
交付包 board-delivery-1.0.0.tar.gz 160M
四、它怎么工作
从一张 Dockerfile 到一个能搬走的包,是五步:
① 构建 在我们这边把应用镜像做出来,版本号取自代码里自己的那一份声明
↓
② 备料 确保数据库镜像也在本地(不在就取一次)
↓
③ 立据 对包内每一个文件算 sha256,写进 MANIFEST.sha256
↓
④ 打包 整个目录压成一个 tar.gz,这是它上搬运通道时的形态
↓
⑤ 搬运 穿过介质缝隙;到对面之后第一件事是对这份清单,而不是先安装
第 ③ 步是这五步里唯一"凭空多出来"的一步:它不产出任何功能,它只产出一件东西——让对面能在动手之前判断"这份包有没有坏"。
五、它会带出哪些概念
- 内网隔离:正因为对面没有出口,这个包才必须自带镜像、自带脚本、自带证明。→ 01 页
- 实例:同一个包在一台机器上可以装出多套互不干扰的部署,靠的是包外的那一份配置。→ 02 页
- 迁移与结构版本:包里的镜像与对面的数据库之间隔着一个版本号,装和升都要先把它对齐。→ 03 页
- 停机窗口:包里编排文件上那个数,决定停栈时手上的活会不会丢。→ 04 页
六、回到应用课
| 应用课里的那句话 | 现在你知道它为什么成立 |
|---|---|
| "把跑起来所需的一切放进一个能被搬动的介质里" | "一切"要落到具体文件上:两个镜像、一份编排、一份模板、四个脚本、一份清单 |
| "装什么必须提前就在介质里,现场没有可装的东西" | 所以编排文件里只有 image:、没有 build:;镜像只能随包直送 |
| "跨过那条介质缝隙之后,第一件要能做的事是「这份包有没有坏」" | 那一件东西就是 MANIFEST.sha256,它存在的理由只有这一个 |
"env.example 里密码位是空的" |
密钥不进包——它只能在生成现场配置那一刻产生 |
这一页改变了你的哪个判断:拿到一个交付目录,你不再先问"东西齐不齐",而是先问**"这里面哪几样丢了要回到有外网那台机器重来、哪几样随时能再生"**——前一类只有 MANIFEST.sha256 和 images/ 下那两个 tar。
→ 这一页的展开在应用课 01 章 · 为什么「私有化」不是「多买一台服务器」。
自测题
- 一个交付包里,哪几样东西丢了就必须回到有外网的那台机器上重打一次?其余的为什么随时能再生?
- 包内的
board__1.0.0.tar为什么不压缩,而外面还要再压一层.tar.gz?