KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
03 · 把自己的东西装进去 — keel 龙骨
前两章装的是我们的程序。这一章把它换成你自己的: 先看清「你的东西」在交付包里占哪一块,再知道怎么把它重新打进去。
前两章装的是我们的程序。这一章把它换成你自己的:
先看清「你的东西」在交付包里占哪一块,再知道怎么把它重新打进去。
一、包里的重量,几乎不在你的代码上
一个应用镜像拆开看是这样的:
| 那一层 | 大小 | 是什么 |
|---|---|---|
基础镜像 python:3.12-slim |
179MB | Python 运行时本身,你改不动它 |
| 依赖层(venv) | 28.2MB | requirements.txt 装出来的东西(venv 是一个独立的依赖目录,跟系统 Python 隔开) |
| 应用代码层 | 61.4kB | 你自己的程序 |
合计(board:1.0.0) |
215MB | 上面三层叠出来的镜像(层就是一层层叠上去的目录快照) |
一行话记住:你的代码 61.4kB,它的运行环境 215MB——交付的重量不在你的代码上。
所以「换掉自己的东西」这件事,你要动的是两个文件位置,而不是层层重写:
app/board/ 你的程序住的地方(谁在包里的名字就叫这个目录)
app/requirements.txt 你的依赖(没有第三方依赖就留空)
Dockerfile 决定上面那几层怎么叠(一般不用改)
二、把它重新打成一个交付包
改完你的程序,在有外网的那一侧跑这条:
./deploy/build-bundle.sh 1.0.0
预期输出(节选,五段一路向下):
==> 构建 board:1.0.0
==> 确保数据库镜像在本地:postgres:16-alpine
==> 组装交付包
==> 计算制品哈希
==> 打包
==> 完成:.../board-delivery-1.0.0.tar.gz(160M)
包内容:
MANIFEST.sha256
compose.yml
env.example
images/board__1.0.0.tar
images/postgres__16-alpine.tar
install.sh
...
看两件事就够:最后那一行给出了包的大小,而包内容里两只镜像 tar 都在。
最常漏的就是第二只——postgres__16-alpine.tar。应用镜像打得再干净,
客户机器上没有 postgres,compose 一样会去 pull,然后在内网里挂到超时。
⚠️ 这只包必须先导进去,现场才可能起得来。 镜像没导进去时,
compose 的默认行为是去仓库取,于是你会得到一段几十秒的等待加一句看起来像网络问题的报错;
加上--pull never之后,同一个场景变成立刻报错:Error response from daemon: No such image: postgres:16-alpine (退出码 1)一句即时的
No such image,好过一句迟到的failed to resolve reference。
三、最容易看错的那个点:版本号有两个来源
build-bundle.sh 会先做一件事——把代码里的版本号和命令行给的版本号对齐,不一致就当场停下:
[失败] 版本号不一致:代码里是 1.0.0,命令行给的是 1.1.0。
先改 app/board/__init__.py 的 __version__,再打包 —— 否则制品与自述对不上。
这条检查存在的理由,是私有化交付里最容易犯的一类错:参数是给人看的,代码里的那个才是给机器看的。
你改了代码、忘了改代码里的版本号,打出来的包会顶着旧版本号流转,
到了现场谁也说不清「这台机器上到底是哪一版」。
顺带一个改代码时的手感问题:Dockerfile 把 requirements.txt 单独 COPY 一次、再 COPY 代码,
于是第二次构建(没动依赖)会看到
#6 CACHED ... #12 CACHED
#13 DONE 0.1s
改代码不会触发重装依赖,因为依赖那一层的输入没变。这不是巧合,是刻意把两层分开的收益。
四、它不是什么
build-bundle.sh不是安装脚本。 它跑在有外网的那一侧(我们这边);
客户那侧用的是第 2 章的install.sh。两个脚本隔着一段没有出口的路,别拿错。- 「改一行代码」不等于「包里换了新版本」。 你改了
app/board/里的东西,
但没重新跑build-bundle.sh,交付包里躺着的仍然是旧镜像——装到现场的还是旧程序。
镜像和容器是两件事:要换的是那只 tar,不是那次运行。
读完你能做什么
- 说出交付包里「你的东西」只占 61.4kB,而重量在运行环境那 215MB 上;
- 用一条命令把自己的程序重新打成交付包,并认出「两只镜像 tar 都在」这个成功形状;
- 说清「版本号两个来源」为什么必须对齐,以及漏打一次包会发生什么。
下一步:你已经会打包、会落地了。最后一章换个方向——
先说清什么情况下别做私有化,再告诉你往下该去哪。