PyTorch 官方提供了预装 CUDA 和 cuDNN 的 Docker 镜像,但把镜像跑起来并不等于 GPU 就能被容器内的进程调用。宿主机上执行 nvidia-smi 一切正常,进入容器后却提示 CUDA driver version is insufficient 或者 torch.cuda.is_available() 返回 False,这种情况并不少见。核心原因是容器默认共享宿主机的内核,但 GPU 设备节点(如 /dev/nvidia0)和驱动库(如 libcuda.so)并不会自动映射进容器,需要借助 NVIDIA Container Toolkit 将宿主机上的 GPU 驱动和运行时挂载到容器内部。

下面从环境准备、镜像选择、启动参数和故障排查几个角度,把 PyTorch 容器化部署中 GPU 支持的完整链路梳理清楚。
为什么容器默认看不到 GPU
Docker 容器并不是虚拟机,它不会虚拟出一套完整的硬件环境。容器与宿主机共享同一个 Linux 内核,但默认情况下,容器只能看到 CPU、内存、网络等通用资源,而 GPU 这类需要专有驱动和内核模块的设备不会自动暴露给容器。对于 NVIDIA GPU 来说,宿主机上必须安装与内核版本匹配的 NVIDIA 驱动,并且需要加载 nvidia_uvm、nvidia_drm 等内核模块。如果这些模块没有加载,容器内即使是 root 用户也无法访问 /dev/nvidia* 设备文件。
即使宿主机驱动正常,Docker 默认的运行时也不认识 GPU 这个资源类型。早期社区通过 --device 参数手动映射设备文件的方式可以临时解决问题,但这种方式在驱动升级或使用多 GPU 时非常脆弱。NVIDIA 后来推出了 NVIDIA Container Toolkit,它向 Docker 注册了一个新的运行时(nvidia-container-runtime),使 docker run 命令支持 --gpus 参数,并在容器启动时自动完成设备节点、驱动库和二进制文件的挂载。
安装与配置 NVIDIA Container Toolkit
要让 Docker 具备 GPU 透传能力,第一步是确认宿主机已经安装 NVIDIA 驱动,并且驱动版本满足容器内 CUDA 的要求。可以通过 nvidia-smi 查看驱动版本和 CUDA 支持的最高版本。接下来安装 NVIDIA Container Toolkit。不同 Linux 发行版的安装命令略有差异,下面以 Ubuntu 为例:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list sudo apt-get update sudo apt-get install -y nvidia-container-toolkit sudo systemctl restart docker
安装完成后,Docker 的配置文件 /etc/docker/daemon.json 中需要注册 nvidia-container-runtime 作为默认运行时,或者至少保证可以通过 --runtime 参数指定。如果不做这步,docker run --gpus all 会报错 unknown flag: --gpus。可以通过以下命令验证运行时是否可用:
sudo nvidia-ctk runtime configure --runtime=docker sudo systemctl restart docker docker info | grep -i runtime
输出中如果能看到 nvidia 字样,说明配置生效。这时再运行一个简单的 CUDA 容器测试:
docker run --rm --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi
如果这条命令能打印出宿主机 GPU 信息,就代表容器已经可以访问 GPU 了。
选择合适的 PyTorch 镜像
PyTorch 官方在 Docker Hub 上提供了多种标签的镜像,主要区分点在于是否包含 CUDA、cuDNN 以及对应的版本。对于训练任务,通常选择带 CUDA 和 cuDNN 的 devel 版本,因为编译扩展或运行调试工具需要头文件和静态库。如果只是推理,可以选择 runtime 版本,体积更小。标签命名规则一般为 pytorch/pytorch:版本号-cuda版本-cudnn版本-运行时类型,例如 pytorch/pytorch:2.3.0-cuda12.1-cudnn8-devel。
选择镜像时需要注意宿主机驱动的兼容性。NVIDIA 驱动向后兼容 CUDA 版本,也就是说驱动版本必须大于等于容器内 CUDA 版本所要求的最低驱动版本。如果驱动太旧,容器启动后运行 PyTorch 会报 CUDA driver version is insufficient for CUDA runtime version。可以通过 nvidia-smi 右上角显示的 CUDA Version 来快速判断宿主机支持的 CUDA 上限,但这个数字表示的是驱动支持的最高 CUDA 版本,并不是宿主机已安装的 CUDA 工具包版本。
另外,如果需要在容器内编译自定义 CUDA 算子,建议使用 devel 镜像,并挂载足够的存储空间。对于大多数用户来说,直接拉取官方镜像是最省事的方式,但如果需要定制环境,也可以基于 nvidia/cuda 基础镜像自己构建,安装 PyTorch 的 pip 包。
Docker 与 Compose 中的 GPU 配置
在 Docker 命令行中,--gpus 参数可以指定暴露给容器的 GPU 数量或具体设备。最常用的写法是 --gpus all,表示把所有 GPU 都分配给容器。也可以使用 --gpus device=0,1 这种形式只暴露部分 GPU,注意在 shell 中需要正确转义引号。如果使用 Docker Compose,配置稍微复杂一些,因为 Compose 的 resources 字段需要遵循 Docker Engine 的 device 请求格式。
下面是一个 docker-compose.yml 的示例,它启动一个 PyTorch 训练容器并分配所有 GPU:
version: "3.8"
services:
training:
image: pytorch/pytorch:2.3.0-cuda12.1-cudnn8-devel
command: python train.py
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
volumes:
- ./data:/workspace/data
- ./models:/workspace/models
working_dir: /workspace
需要注意的是,deploy 字段在 docker-compose up 命令下不会生效,它原本是用于 Docker Swarm 模式。对于本地单机使用,需要配合 docker-compose 的 --compatibility 参数,或者改用 Docker Compose V2 支持的 gpu 字段。从 Compose V2 开始,可以直接在服务下使用 gpu 配置:
services:
training:
image: pytorch/pytorch:2.3.0-cuda12.1-cudnn8-devel
gpu: all
command: python train.py
这种写法更简洁,但要求 Docker Compose 版本不低于 2.0 且 Docker Engine 已启用 GPU 支持。如果使用旧版 Compose,建议还是通过 docker run 或者 shell 脚本来规避兼容性问题。
验证 GPU 与常见故障排查
容器启动后,第一步应该确认 GPU 是否可见。除了执行 nvidia-smi,还可以在 Python 中检查 PyTorch 的 CUDA 状态:
import torch print(torch.cuda.is_available()) print(torch.cuda.device_count()) print(torch.cuda.get_device_name(0))
如果输出为 True 和正确的设备数量,说明 GPU 支持已经打通。如果返回 False,可以从几个方向排查:宿主机驱动版本是否过低、容器内 CUDA 版本是否与驱动匹配、是否忘记加 --gpus 参数、以及 nvidia-container-toolkit 是否安装并重启了 Docker。另一个常见问题是容器内显存占用过高导致 OOM,这时可以通过 nvidia-smi 查看显存占用,并在训练代码中设置 batch size 或使用梯度累积来降低显存需求。
还有一种情况是多个容器争抢 GPU,导致性能下降或显存不足。可以通过 --gpus 参数限制每个容器使用的 GPU 编号,或者使用 CUDA_VISIBLE_DEVICES 环境变量在应用层面控制可见设备。但环境变量方式在容器内设置时,需要确保它先于 PyTorch 初始化生效。
最后,建议将验证步骤固化到 CI 或启动脚本中,每次部署前自动执行 torch.cuda.is_available() 检查,避免带病上线。这样一套完整的 GPU 容器化方案就能稳定支撑训练和推理任务。

