Docker 容器内使用宿主机的 GPU
为什么需要在 Docker 容器里使用 GPU?
在深度学习、科学计算等场景中,GPU 的并行计算能力至关重要。Docker 提供了轻量级隔离环境,将 GPU 暴露给容器可以让你:
- 隔离实验环境,避免宿主机驱动冲突
- 快速复现模型训练或推理结果
- 在 CI/CD 流程中无缝执行 GPU 任务
本教程将带你一步步实现从宿主机调用 GPU 到 Docker 容器。
前提条件
在开始之前,请确保你的宿主机满足以下要求:
- 物理机或虚拟机已正确安装 NVIDIA 显卡
- 宿主机已安装 NVIDIA GPU 驱动程序(版本 ≥ 450.80.02)
- 已安装 Docker(版本 ≥ 19.03)
- 推荐使用 Docker Compose (可选,方便管理多容器应用)
验证宿主机 GPU 状态
在宿主机终端执行以下命令,确认驱动和 GPU 可用:
nvidia-smi
如果输出显示 GPU 信息(型号、驱动版本、CUDA 版本等),说明驱动安装正确。
安装 NVIDIA Container Toolkit
原生的 Docker 不支持将 GPU 直接传递给容器,需要借助 NVIDIA Container Toolkit。该工具扩展了 Docker 的运行时,使容器可以调用宿主机 GPU。
步骤一:设置软件包仓库
Ubuntu/Debian 系统执行:
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
CentOS/RHEL 系统执行:
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \
sudo tee /etc/yum.repos.d/nvidia-docker.repo
步骤二:安装 nvidia-docker2 及运行时
更新软件包索引并安装:
sudo apt-get update
sudo apt-get install -y nvidia-docker2
或使用 yum:
sudo yum install -y nvidia-docker2
步骤三:重启 Docker 服务
sudo systemctl restart docker
步骤四:验证安装
运行以下测试容器,若能正确输出 nvidia-smi 结果则表示安装成功:
docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
运行带有 GPU 访问权限的容器
NVIDIA Container Toolkit 安装完成后,Docker 命令中通过 --gpus 参数指定 GPU 使用方式。
基础用法:将所有 GPU 分配给容器
docker run --rm --gpus all nvidia/cuda:12.3.1-base-ubuntu22.04 nvidia-smi
--gpus all:将宿主机所有可用 GPU 暴露给容器。nvidia/cuda:12.3.1-base-ubuntu22.04:包含 CUDA 运行时的基础镜像,你也可以使用其他支持 CUDA 的镜像。nvidia-smi:容器启动后执行的命令,用来验证 GPU 是否可见。
指定特定 GPU
如果你有多张显卡,只希望容器使用其中一部分,可以用设备索引或 UUID 指定:
# 使用索引(0 代表第一张 GPU)
docker run --rm --gpus '"device=0"' nvidia/cuda:12.3.1-base-ubuntu22.04 nvidia-smi
# 使用 GPU 的 UUID(通过 nvidia-smi 查询)
docker run --rm --gpus '"device=GPU-<你的UUID>"' nvidia/cuda:12.3.1-base-ubuntu22.04 nvidia-smi
# 指定多张 GPU,用逗号分隔
docker run --rm --gpus '"device=0,2"' nvidia/cuda:12.3.1-base-ubuntu22.04 nvidia-smi
使用环境变量控制可见 GPU
也可以通过 NVIDIA_VISIBLE_DEVICES 环境变量控制 GPU 访问:
docker run --rm --env NVIDIA_VISIBLE_DEVICES=0,1 nvidia/cuda:12.3.1-base-ubuntu22.04 nvidia-smi
在容器内运行深度学习框架示例
以 TensorFlow 和 PyTorch 为例,展示如何在 GPU 加速容器中执行代码。
TensorFlow 示例
创建并运行一个临时 GPU 容器,并运行 Python 检测 GPU:
docker run --rm --gpus all -it tensorflow/tensorflow:latest-gpu bash
进入容器后执行:
python -c "import tensorflow as tf; print(tf.config.list_physical_devices('GPU'))"
如果成功输出 [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')],说明 TensorFlow 已识别到 GPU。
PyTorch 示例
官方 PyTorch 镜像已内置 CUDA,直接运行:
docker run --rm --gpus all -it pytorch/pytorch:latest bash
在容器中执行:
python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))"
返回 True 和 GPU 型号即表示成功。
Docker Compose 中启用 GPU
如果你使用 Compose 管理服务,可在 compose.yml 中通过 deploy 资源来声明 GPU。
Compose file 版本要求
确保使用 Compose file format 2.3 或更高版本,且 Docker Compose 版本 ≥ 1.28.0 才原生支持 --gpus。
version: '3.8'
services:
gpu-test:
image: nvidia/cuda:12.3.1-base-ubuntu22.04
command: nvidia-smi
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1 # 使用 1 张 GPU
capabilities: [gpu] # 可添加 compute, utility 等
启动服务:
docker compose up
如果你需要指定 GPU 设备索引,可以添加 device_ids:
deploy:
resources:
reservations:
devices:
- driver: nvidia
device_ids: ['0', '1']
capabilities: [gpu]
检查容器内的 CUDA 版本与驱动兼容性
容器的 CUDA 工具包版本必须与宿主机驱动的最低支持版本兼容。你可以在容器内运行 nvidia-smi 查看驱动版本和最大支持 CUDA 版本。若容器内的 CUDA 版本过高,可能导致运行时错误。
最简单的方案是:选择与宿主机驱动匹配的 CUDA 基础镜像(如 nvidia/cuda:11.8-base)。宿主机驱动支持情况可通过 nvidia-smi 右上角的 “CUDA Version” 查看,它代表该驱动最高支持的 CUDA 版本。
排除故障
问题 1:docker run 提示 Unknown runtime specified nvidia
原因:Docker 守护进程没有加载 nvidia runtime。
解决:编辑 /etc/docker/daemon.json,确保 runtime 配置正确:
{
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
}
}
之后重启 Docker:
sudo systemctl restart docker
问题 2:在容器内 nvidia-smi 输出 Failed to initialize NVML: Unknown Error
原因:宿主机驱动与 Container Toolkit 版本不兼容,或容器使用的 CUDA 镜像版本过高。
解决:
- 更新宿主机驱动至最新稳定版。
- 使用与驱动匹配的较低 CUDA 版本镜像尝试。
问题 3:容器使用 --gpus all 后,训练仍只用到 CPU
原因:代码中可能没有指定 tf.device('/GPU:0') 或 torch.device('cuda'),默认使用 CPU。
解决:在代码中明确将张量或模型移动到 GPU 设备。
进阶:多容器共享 GPU 与 GPU 虚拟化
Kubernetes 或 Docker Swarm 等编排平台支持更细粒度的 GPU 共享。NVIDIA 提供了 GPU Operator 和 MIG(多实例 GPU)技术(仅部分专业卡支持),可以将一张 GPU 划分为多个独立实例。这超出了本教程范围,但你可以在掌握基础用法后进一步探索。
总结
通过 NVIDIA Container Toolkit,你可以轻松地将宿主机 GPU 共享给 Docker 容器,从而在隔离环境中运行 CUDA 应用。关键步骤总结:
- 宿主机安装 NVIDIA 驱动
- 安装 NVIDIA Container Toolkit
- 使用
docker run --gpus或 Compose file 指定 GPU - 验证容器内 GPU 可见性
现在,你可以将模型训练、推理等任务封装进可移植的 GPU 容器,让开发与部署更加一致、高效。