安装 `nvidia-docker2` 并验证 `nvidia-smi` 在容器内输出

解读

在国内面试场景里,这道题表面考“装个包、跑条命令”,实则同时检验候选人对 GPU 容器化全链路的掌握深度与生产落地经验
面试官期望你在 5~10 分钟内把宿主机驱动 → Docker 版本 → nvidia-docker2 仓库 → 运行时配置 → 镜像选择 → 隔离与可观测性这一整条闭环讲清楚,并给出可复现、可运维、可排障的最小步骤。
任何一句“先装驱动”却不提内核版本与驱动签名、任何一步“跑个 nvidia/cuda 镜像”却不提国内镜像源加速与多架构校验,都会被追问到哑口无言。

知识点

  1. 宿主机前置条件:CentOS 7/8、Ubuntu 20.04/22.04 内核 ≥4.15,官方 NVIDIA 驱动 ≥ 450.80.02,且禁用 nouveau
  2. Docker 版本锁口20.10.7 以上且低于 24.x(nvidia-docker2 官方兼容性矩阵),yum/apt 仓库优先用国内清华/中科大镜像
  3. nvidia-docker2 本质把 nvidia-container-runtime 注册为 Docker 的额外 runtime不替换 dockerd,通过 OCI prestart hook 把宿主机 GPU 字符设备与库文件挂载进容器。
  4. 配置验证/etc/docker/daemon.json 中必须出现 "runtimes": { "nvidia": { "path": "nvidia-container-runtime", "runtimeArgs": [] } }reload 后 docker info | grep nvidia 需回显
  5. 镜像策略官方 nvidia/cuda:11.8.0-base-ubuntu22.04 镜像国内拉不动时,先用 docker pull registry.cn-hangzhou.aliyuncs.com/nvidia/cuda:11.8.0-base-ubuntu22.04,再 retag 保持名称一致,避免 CI 脚本耦合。
  6. 安全加固容器内默认 root,面试必须补充 -u 1000:1000 --group-add video 以及 只读挂载 /sys 以外的敏感路径Secrets 通过 --env-file 或 docker secret 管理绝不硬编码 NVIDIA_VISIBLE_DEVICES
  7. 排障三板斧
    • nvidia-container-cli info 查看驱动与设备是否匹配;
    • docker run --rm --gpus all ubuntu:22.04 nvidia-smi“could not select device driver” 时,优先检查 /dev/nvidiactl 权限与 SELinux 标签
    • dmesg 出现 “NVRM: GPU 0000:3b:00.0 Failed to allocate video memory” 代表宿主机驱动与容器内 CUDA 版本不匹配,需重新打标签或升级驱动

答案

以下步骤在 CentOS 7.9 宿主机 + 官方驱动 525.60.13 + Docker 20.10.24 环境验证通过,全程使用国内源可直接写进面试白板

  1. 宿主机准备

    sudo yum install -y yum-utils
    sudo yum-config-manager --add-repo https://mirrors.tuna.tsinghua.edu.cn/nvidia-docker/centos7/x86_64/nvidia-docker.repo
    sudo yum install -y nvidia-driver-latest-dkms
    sudo reboot   # 重启后 nvidia-smi 正常输出
    
  2. 安装 Docker 并锁定版本

    sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    sudo yum install -y docker-ce-20.10.24 docker-ce-cli-20.10.24 containerd.io
    sudo systemctl enable --now docker
    
  3. 安装 nvidia-docker2

    sudo yum install -y nvidia-docker2
    sudo tee /etc/docker/daemon.json <<EOF
    {
      "runtimes": {
        "nvidia": {
          "path": "nvidia-container-runtime",
          "runtimeArgs": []
        }
      },
      "registry-mirrors": ["https://registry.docker-cn.com"]
    }
    EOF
    sudo systemctl restart docker
    
  4. 验证运行时

    docker info | grep nvidia   # 应出现 runtimes: nvidia
    
  5. 拉取国内加速镜像并验证 nvidia-smi

    docker pull registry.cn-hangzhou.aliyuncs.com/nvidia/cuda:11.8.0-base-ubuntu22.04
    docker tag registry.cn-hangzhou.aliyuncs.com/nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia/cuda:11.8.0-base-ubuntu22.04
    docker run --rm --gpus all nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia-smi
    

    终端回显 GPU 型号、驱动版本、CUDA 版本即判定通过

  6. 加分项:非 root 用户执行

    docker run --rm --gpus all -u 1000:1000 --group-add video nvidia/cuda:11.8.0-base-ubuntu22.04 nvidia-smi
    

    无权限报错则证明隔离正确

拓展思考

  1. 多卡调度:如果宿主机有 8 张 A100,如何通过 NVIDIA_VISIBLE_DEVICES=4,5,6,7CUDA_VISIBLE_DEVICES 的联动让训练容器只看到后 4 卡同时保证 metrics-exporter 采集的 GPU 序号与宿主一致
  2. Kubernetes 场景nvidia-device-plugin 已经不再依赖 nvidia-docker2而是直接调用 nvidia-container-toolkit如何在离线机房通过 helm install gpu-operator 一键完成驱动 + container-toolkit + device-plugin 的协同升级并保证节点 NotReady 时间 <30s
  3. 国产化替代在鲲鹏 + 昇腾 910B 环境没有 nvidia-docker2如何使用 ascend-docker-runtime 把 Ascend 驱动注入容器并复用同一条 docker run --device /dev/davinci0 语义
  4. 安全合规金融客户要求容器内不能出现宿主机驱动版本信息如何通过自定义 nvidia-container-runtime hook 把 /proc/driver/nvidia/version 屏蔽同时又不影响 CUDA 调用