前两章我们搭好了镜像骨架、讲透了 GPU 透传与隔离的本质。这一章不再停留在 hello-world 级的 demo,而是把工业界真实会遇到、也最容易踩坑的两类负载搬进沙箱:一类是训练 / 微调任务,特点是长时、多卡、重 IO、要留日志和断点;另一类是推理服务,特点是常驻、要稳、要对外暴露、要控资源。这两类负载对沙箱的要求几乎是"两个极端",对应的 Docker 写法也完全不同。
本章 4.1 拆解训练任务沙箱化,4.2 拆解推理服务沙箱化。读完这两节,你应该能把手上任何一个真实模型项目,干净地装进一个可复现、可迁移、不留"我机器上能跑"后遗症的沙箱。
本章 4.1 拆解训练任务沙箱化,4.2 拆解推理服务沙箱化。读完这两节,你应该能把手上任何一个真实模型项目,干净地装进一个可复现、可迁移、不留「我机器上能跑」后遗症的沙箱。
为了避免你读到一半忘了目标,先给出这一章结束时你应当能独立说出的三句话:
如果你读完两节后能用上面三句话复述,说明这一章真的进了你的知识体系,而不是「看过了」。带着这三句话去读 4.1 和 4.2,你会更容易抓住每节的重心。
训练任务和推理服务,在资源模型上是两种完全不同的东西,很多团队一开始用同一套模板去套,结果要么训练把盘写满,要么推理半夜 OOM 被 kill。
一个很现实的判断标准:看进程会不会自己退出。训练脚本跑完主循环就 exit 0,容器随之停止;推理服务是 while True 永远不退出。这个差异直接决定了你是该用 docker run 一次性跑,还是该用 docker compose + 重启策略把它当服务养着。
原理讲得再透,落到真实项目里依然会卡在细节:数据集几十 GB 怎么挂?多卡训练 NCCL 通信为什么在容器里失败?推理暴露端口后外部为什么连不上?这些都不是"原理"能直接回答的,需要的是经过验证的、能直接复用的工程写法。
这一章给出的不是"标准答案"(因为不同框架、不同硬件差异很大),而是一套决策框架和可套用的模板骨架:你照着填空,就能避开 90% 的新手坑。凡涉及具体版本号、默认开关、命令参数,文中会明确标注"以你所用版本官方说明为准",绝不臆造运行结果。
建议先读 4.1,建立"训练负载"的沙箱心智模型——重点理解多卡协同对网络与设备视图的要求、以及数据卷为什么是训练沙箱的命门;再读 4.2,看服务化如何反过来约束设计——端口、健康检查、资源上限成了主角。两节都假设你已完成第二章的镜像骨架,可以直接复用其中的基础镜像与依赖层,不必从零再来一遍。
为什么训练沙箱和推理沙箱几乎是两个物种:训练追求「一次跑完、产出落盘、能续跑」,所以它的关键词是挂载卷、续跑逻辑、--shm-size;推理追求「永远在线、稳如老狗、被调得动」,所以它的关键词是重启策略、端口映射、资源上限、健康探活。把这两套模板都收进 compose 文件,你就拥有了从「数据进沙箱训练」到「模型出沙箱服务」的完整链路。
为了避免你读成孤立的几篇,这里明确第四章在整本书里的位置:
--gpus 透传会显得没来由。一句话:第二章给你「积木」,第三章给你「积木为什么这样拼」,第四章给你「拼成一个能跑的真实东西」,第五章给你「怎么把这套拼法变成团队标准」。
读到这里你也许发现,本章几乎没有「新原理」,全是「把前面原理落到具体场景的写法」。这恰恰是沙箱化最容易被低估的价值:它把团队里那些「只有老手知道」的隐性经验,固化成了可复制的文本。
--shm-size」——以前是口口相传的踩坑教训,现在写进 compose,新人不会再踩。:ro 一行配置。--resume 的标准动作。所以当你把训练、推理两套模板都写进仓库的 compose 文件,你交付的不只是「两个能跑的服务」,而是一份「团队不会因为人员流动而丢失的工程资产」。这正是体系化教程想传递的核心理念:工具用法的价值是有限的,把用法沉淀成可复用的资产,价值才是长期的。
下一节,我们从一个最朴素的训练命令开始,一步步把它改造成生产可用的沙箱写法。