3. 容器运行时选型与安装
在 Jetson 上跑容器,第一件要决定的事不是“装哪个镜像”,而是“用哪条运行时链路”。Jetson 的 GPU 访问依赖 NVIDIA 驱动暴露的 /dev/nvidia* 设备节点、驱动库以及 CUDA 兼容层,普通容器默认看不到这些资源。因此,无论选择 Docker 还是 containerd,都必须把 NVIDIA Container Toolkit 接入运行时,让容器创建时自动完成设备与库的注入。
Docker 与 containerd 的定位差异
Docker 是面向开发者的完整工具链,包含 CLI、镜像构建、网络与卷管理、Compose 等;containerd 是更底层的容器运行时,负责镜像拉取、容器生命周期和快照管理,通常由 Kubernetes 通过 CRI 调用。在 Jetson 单机开发场景中,Docker 的交互效率更高;在边缘集群或 K3s 场景中,containerd 更贴近生产形态。
| 对比项 | Docker (dockerd) | containerd |
|---|---|---|
| 调用入口 | docker CLI / Docker API | ctr、crictl、CRI 接口 |
| GPU 注入方式 | 通过 --gpus all 或 --runtime=nvidia | 通过 CRI 运行时类 nvidia 或 runtimeClassName |
| 典型使用场景 | 单机开发、调试、快速验证 | K3s/K8s 节点、边缘集群 |
| 与 Toolkit 集成点 | /etc/docker/daemon.json 注册 nvidia runtime | /etc/containerd/config.toml 配置 runtime class |
两者并非互斥:Docker 内部也使用 containerd 作为底层运行时,只是 Docker 在其上封装了更友好的接口。选型时可按“是否需要 Kubernetes 编排”来判断:需要则优先 containerd,不需要则 Docker 更省心。
NVIDIA Container Toolkit 安装
NVIDIA Container Toolkit 提供 nvidia-container-runtime、nvidia-container-cli 和 nvidia-ctk 等组件,负责在容器启动时挂载 GPU 设备、驱动库和 CUDA 兼容文件。在 Jetson 上,推荐使用 NVIDIA 官方 apt 源安装,避免与 L4T 自带驱动版本冲突。
# 1. 添加 NVIDIA 容器工具链 GPG 密钥与软件源
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey \
| sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
| sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' \
| sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
# 2. 安装工具链
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
# 3. 确认版本
nvidia-container-toolkit --version
nvidia-ctk --version
安装完成后,系统会新增 /usr/bin/nvidia-container-runtime 与 /usr/bin/nvidia-container-toolkit。此时运行时尚未被 Docker 或 containerd 调用,需要显式注册。
nvidia-container-runtime 配置
配置的核心是让容器运行时在创建容器时调用 nvidia-container-runtime,由它读取镜像的 CUDA 版本、驱动能力并注入对应文件。Docker 场景下使用 nvidia-ctk runtime configure 自动写入配置:
# Docker 场景:注册 nvidia runtime 并设为默认
sudo nvidia-ctk runtime configure --runtime=docker --set-as-default
sudo systemctl restart docker
# 验证 daemon.json 中已出现 nvidia runtime
cat /etc/docker/daemon.json
执行后 /etc/docker/daemon.json 中会出现类似片段:
{
"runtimes": {
"nvidia": {
"path": "nvidia-container-runtime",
"runtimeArgs": []
}
},
"default-runtime": "nvidia"
}
containerd 场景则使用:
sudo nvidia-ctk runtime configure --runtime=containerd
sudo systemctl restart containerd
该命令会在 /etc/containerd/config.toml 中写入 nvidia runtime class,并配置 BinaryName = "/usr/bin/nvidia-container-runtime"。若使用 K3s,还需在 /var/lib/rancher/k3s/agent/etc/containerd/config.toml.tmpl 中同步该配置,否则节点重启后会被覆盖。
验证:从容器内看到 GPU
配置完成后必须验证,否则很容易出现“容器能启动但看不到 GPU”的隐性故障。最直接的验证方式是运行一个带 CUDA 基础环境的镜像,并在容器内执行 nvidia-smi 或 tegrastats。
# Docker 验证:使用 L4T 基础镜像
docker run --rm --gpus all nvcr.io/nvidia/l4t-base:r35.4.1 nvidia-smi
# 若未设置默认 runtime,也可显式指定
docker run --rm --runtime=nvidia nvcr.io/nvidia/l4t-base:r35.4.1 nvidia-smi
预期输出中应能看到 Jetson 的 GPU 型号、驱动版本以及 CUDA 版本。若报错 could not select device driver "" with capabilities: [[gpu]],说明 Docker 未注册 nvidia runtime;若报错 nvidia-container-cli: mount error,通常是驱动库路径或 L4T 版本与镜像不匹配。
containerd 场景可用 crictl 验证:
sudo crictl run --runtime nvidia \
--image nvcr.io/nvidia/l4t-base:r35.4.1 \
--command "nvidia-smi"
若使用 K3s,可在 Pod 中指定 runtimeClassName: nvidia,再通过 kubectl logs 查看 nvidia-smi 输出。验证通过后,建议把验证命令固化为部署前的检查项,避免每次换镜像或升级 L4T 后重复排查。
l4t-base:r35.4.1 或 l4t-cuda:r35.4.1,跨大版本(如 r32 与 r35)混用常导致 libcuda.so 加载失败。
nvidia-ctk runtime configure --set-as-default 后,所有容器默认走 nvidia runtime。若某些容器不需要 GPU,仍可正常启动,但会多一次运行时判断;若追求极致启动速度,可保留默认 runtime 为 runc,仅在需要 GPU 的容器上显式指定 --runtime=nvidia。