1.4 常见疑问速答:把"隔离式沙箱"讲清楚前先扫清误解 前面三节把"痛点""隔离的本质""技术选型"都铺开了。这一节专门收口新手最常抛出的七个疑问。我故意把它们堆在一起,是因为这些问题彼此关联,单独回答容易越解释越乱。先扫清误解,第二章动手时才不会被"可是……"打断。 疑问一:容器里到底有没有装 GPU 驱动? 这是被问得最多、也最容易答错的问题。标准答案是:容器里不装驱动,驱动只在宿主机内核态运行;容器里只有 CUDA 的用户态运行时库(一堆 )。当你在容器内 并调用 CUDA,真正向硬件发号施令的,是宿主机内核里的 NVIDIA 驱动;容器内的 只是个"传声筒",通过 设备文件和宿主机驱动通信。
前面三节把"痛点""隔离的本质""技术选型"都铺开了。这一节专门收口新手最常抛出的七个疑问。我故意把它们堆在一起,是因为这些问题彼此关联,单独回答容易越解释越乱。先扫清误解,第二章动手时才不会被"可是……"打断。
这是被问得最多、也最容易答错的问题。标准答案是:容器里不装驱动,驱动只在宿主机内核态运行;容器里只有 CUDA 的用户态运行时库(一堆 .so)。当你在容器内 import torch 并调用 CUDA,真正向硬件发号施令的,是宿主机内核里的 NVIDIA 驱动;容器内的 libcuda.so 只是个"传声筒",通过 /dev/nvidia* 设备文件和宿主机驱动通信。
这带来一个关键推论:容器的 CUDA 能力受限于宿主机的驱动版本,而不是镜像里写了多高的 CUDA。比如宿主机驱动只支持到 CUDA 12.2,你容器内镜像写的是 CUDA 12.4,运行时就会报 CUDA driver version is insufficient。所以"选对基础镜像"的前提,永远是"宿主机的驱动先够新"。
因为"宿主机装好"是单点状态,而团队需要的是可复制状态。宿主机装好的环境,只有这台机器有;新人来、机器坏、换云厂商,一切归零。容器把"环境"变成一份文件(镜像),可以存进仓库、拉到任意装了 Docker + 驱动的机器上原样复活。代价只是一点点封装成本,换来的却是"环境即代码"的可迁移性。
默认情况下,如果多个容器都拿到同一张卡的可见性(比如都 --gpus all),它们共享这块卡的全部显存和算力,会互相抢——一个吃满显存,另一个就 OOM。所以"隔离"不是自动发生的,要靠你给每个容器限定不同的 device 或配合 MPS/MIG。第三章会细讲,这里先记住原则:想互不干扰,就必须显式切分设备视图或算力。
虚拟机隔离更强(内核都分开),容器隔离较弱(共享内核,靠 namespace/cgroup)。但大模型团队内部协作,要的是"环境不互踩、可复现",而不是"防住恶意代码"。所以用容器足够,且更轻。只有跑不可信代码、需要不同内核时,才上 VM。这点在 1.3 节的选型决策树里已经给过结论。
值得,但要调低预期。单卡单机时,沙箱主要的收益是可复现和整洁:你的实验环境、依赖、数据挂载都规范化,换机器、重装系统、给同事复现都省事。多卡、多人、多机时,收益才指数级放大。换句话说,沙箱不是"大团队专利",而是"好习惯的起点"。
一句话:镜像是"模板/蓝图",容器是"按蓝图跑起来的实例"。同一份镜像可以同时起多个容器;容器删了,镜像还在;镜像改了,旧容器不受影响(除非重建)。你平时 docker run 是"用镜像造一个容器",docker build 是"把 Dockerfile 做成镜像"。把这对关系记牢,后面所有命令都不会迷路。
不冲突,是层级关系。你先在容器层面把单机沙箱做对(本教程主线),再用 Kubernetes 做多机调度时,你的工作负载已经是一个"干净容器",接入 K8s + Device Plugin 几乎是顺理成章。很多团队正是先有这套单机沙箱经验,才敢上 K8s。反之,一上来就 K8s,往往会被"环境都没钉死"的底层问题反噬。
读完这七条,你应该能在白板上给别人讲清:驱动住哪、库住哪、容器和 VM 差在哪、多容器怎么抢卡、单卡值不值得做、镜像容器什么关系、和 K8s 怎么衔接。这些底气,正是第二章动手搭建骨架前的"安全带"。下一节起,我们正式写配置。