最近在整理一台 Jetson Orin Nano Super 的开发环境时,我准备顺手把 Docker 配好。

一开始很容易按照普通 Ubuntu 的经验去想:

sudo apt install docker.io

或者直接安装 Docker CE。

但 Jetson 和普通 Ubuntu + CPU 主机有一点关键区别:

如果希望容器正常访问 Jetson 的 GPU、CUDA、TensorRT 等 NVIDIA 平台能力,仅有 Docker Engine 是不够的。

Jetson 官方还提供了一层 NVIDIA Container Toolkit / Runtime,用来把 Jetson 的 GPU 与平台能力暴露给容器。

因此完整结构其实是:

Jetson Linux / L4T
│
├── Docker Engine
│
└── NVIDIA Container Toolkit
         │
         └── NVIDIA Container Runtime
                  │
                  ↓
             GPU Container

本文记录在以下环境中的完整安装过程:

Device:       Jetson Orin Nano Developer Kit Super
Architecture: aarch64
Ubuntu:       22.04.5 LTS
L4T:          R36.4.3
JetPack:      6.2.x
Kernel:       5.15.148-tegra

官方参考:

NVIDIA 当前明确将 Docker 用作 Jetson 上可复现的 CUDA / AI 开发环境之一。NVIDIA Docs


1. Jetson 上推荐怎么安装 Docker?

NVIDIA 官方当前给出的安装流程是:

sudo apt update
sudo apt install -y nvidia-container curl

curl https://get.docker.com | sh

sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl daemon-reload
sudo systemctl restart docker

这里其实包含了两套东西:

nvidia-container
    ↓
Jetson / NVIDIA Container Toolkit

Docker Engine
    ↓
普通 Linux container runtime

Docker 官方本身支持 Ubuntu 22.04 和 ARM64,所以 Jetson 的 aarch64 并不是问题。Docker Documentation

如果已经配置过 Docker 官方 APT 源,也可以直接安装:

sudo apt install \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

而不是使用 Ubuntu 自带的 docker.io。

本文机器已经存在:

https://download.docker.com/linux/ubuntu jammy

因此 Docker CE 可以直接通过 APT 安装。

不过实际安装时,我先从 Jetson 侧的 nvidia-container 开始。


2. 安装前先 dry-run

Jetson 上的 CUDA、TensorRT、L4T、JetPack 之间存在比较强的版本关联,可以说,镜像实际上进行了特调,所以直接apt upgrade往往会破坏特调。

因此我不希望为了安装 Docker,顺手触发几百个 JetPack 软件包更新。

先模拟:

sudo apt-get -s install \
  nvidia-container \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

结果却直接出现依赖冲突:

nvidia-container :
 Depends: nvidia-container-toolkit-base (= 1.16.2-1)
          but 1.20.1-1 is to be installed

 Depends: libnvidia-container-tools (= 1.16.2-1)
          but 1.20.1-1 is to be installed

 Depends: nvidia-container-toolkit (= 1.16.2-1)
          but 1.20.1-1 is to be installed

 Depends: libnvidia-container1 (= 1.16.2-1)
          but 1.20.1-1 is to be installed

这不是 Docker 损坏,也不是 dpkg 状态异常。

真正的问题是:

JetPack 6.2.1
└── nvidia-container
      └── 严格要求 Toolkit 1.16.2-1

当前 APT 软件源
└── 同时提供 Toolkit 1.20.1-1

APT 默认选择新版
        ↓
版本依赖冲突

3. 确认 NVIDIA Container Toolkit 版本

查看相关包:

for p in \
  nvidia-container \
  nvidia-container-toolkit \
  nvidia-container-toolkit-base \
  libnvidia-container-tools \
  libnvidia-container1
do
  echo "===== $p ====="
  apt-cache policy "$p" |
    grep -E 'Installed:|Candidate:|1\.16\.2-1|1\.20\.1-1'
done

本文机器实际输出为:

===== nvidia-container =====
Installed: (none)
Candidate: 6.2.1+b38

===== nvidia-container-toolkit =====
Installed: (none)
Candidate: 1.20.1-1
   1.20.1-1 600
   1.16.2-1 600

===== nvidia-container-toolkit-base =====
Installed: (none)
Candidate: 1.20.1-1
   1.20.1-1 600
   1.16.2-1 600

另外两个包情况相同。

这里已经很清楚:

nvidia-container 6.2.1+b38
        ↓
要求 1.16.2-1

APT
        ↓
优先想装 1.20.1-1

这种情况下,我选择服从当前 JetPack 的版本组合,而不是强行追较新的 Toolkit。


4. 显式安装 JetPack 要求的版本

先继续 dry-run:

sudo apt-get -s install \
  nvidia-container=6.2.1+b38 \
  nvidia-container-toolkit=1.16.2-1 \
  nvidia-container-toolkit-base=1.16.2-1 \
  libnvidia-container-tools=1.16.2-1 \
  libnvidia-container1=1.16.2-1

结果:

The following NEW packages will be installed:
  libnvidia-container-tools
  libnvidia-container1
  nvidia-container
  nvidia-container-toolkit
  nvidia-container-toolkit-base

0 upgraded, 5 newly installed, 0 to remove and 899 not upgraded.

这正是希望看到的。

于是正式安装:

sudo apt-get install \
  nvidia-container=6.2.1+b38 \
  nvidia-container-toolkit=1.16.2-1 \
  nvidia-container-toolkit-base=1.16.2-1 \
  libnvidia-container-tools=1.16.2-1 \
  libnvidia-container1=1.16.2-1

5. 一个很 Jetson 的行为:它自己开始装 Docker 了

安装完 nvidia-container 后,我准备继续:

sudo apt install \
  docker-ce \
  docker-ce-cli \
  containerd.io \
  docker-buildx-plugin \
  docker-compose-plugin

结果发现 APT lock 已经被占用:

Could not get lock /var/lib/dpkg/lock-frontend.
It is held by process 34667 (apt-get)

这时候不要删 lock,也不要直接 kill -9。

先看进程:

ps -fp 34667

得到:

apt-get install -y docker-ce docker-ce-cli containerd...

再看父进程:

ps -fp 32056

结果非常有意思:

/bin/bash /etc/systemd/nv-install-docker.sh

继续确认这个脚本来自哪里:

dpkg -S /etc/systemd/nv-install-docker.sh

得到:

nvidia-container: /etc/systemd/nv-install-docker.sh

也就是说:

JetPack 6.2.1 的 nvidia-container 包在这台机器上会通过 systemd 自动运行自己的 Docker 安装脚本。

实际流程变成了:

安装 nvidia-container
        ↓
/etc/systemd/nv-install-docker.sh
        ↓
自动 apt-get install Docker CE
        ↓
enable docker.service
        ↓
写入 NVIDIA runtime 配置

所以这里正确做法反而是什么都不做,让 NVIDIA 自己把安装跑完。

可以通过 journal 查看进度:

journalctl -u nv-install-docker.service -n 50 --no-pager

日志中可以看到:

Setting up docker-ce ...
Setting up docker-compose-plugin ...
Created symlink ... docker.service ...
Docker service installed
Wrote updated config to /etc/docker/daemon.json

因此对于这个版本的 JetPack:

如果安装 nvidia-container 后突然遇到 dpkg lock,先查一下是不是 NVIDIA 的 nv-install-docker.sh 正在后台工作。


6. 检查 Docker

安装结束后:

docker --version
docker compose version
docker buildx version

systemctl is-enabled docker
systemctl is-active docker

本文机器得到:

Docker version 29.9.1
Docker Compose version v5.6.0
github.com/docker/buildx v0.38.0 ...

enabled
active

Docker 本体已经正常。


7. 检查 NVIDIA Runtime

继续:

cat /etc/docker/daemon.json

NVIDIA 已经自动写入:

{
    "runtimes": {
        "nvidia": {
            "args": [],
            "path": "nvidia-container-runtime"
        }
    }
}

但是第一次运行:

sudo docker info | grep -i -A3 runtime

只有:

Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc

原因很简单:

配置已经写入,但 Docker daemon 是在写配置之前启动的。

安装日志本身也提示:

It is recommended that docker daemon be restarted.

因此:

sudo systemctl restart docker

重新检查:

sudo docker info | grep -i -A3 runtime

得到:

Runtimes: io.containerd.runc.v2 nvidia runc
Default Runtime: runc

这就说明 NVIDIA Runtime 已经正确注册。


8. Default Runtime: runc 有问题吗?

没有。

现在是:

Runtimes:
├── runc
└── nvidia

Default Runtime:
└── runc

普通容器继续用 runc。

需要 NVIDIA runtime 时:

docker run --runtime nvidia ...

不过 NVIDIA 当前 Jetson 官方教程进一步建议把:

"default-runtime": "nvidia"

加入 /etc/docker/daemon.json,这样以后运行 Jetson GPU 容器时不用每次显式写 --runtime nvidia。NVIDIA Docs

本文暂时保留,因为 runtime 已经正常注册,而且显式指定更容易看清普通容器和 NVIDIA 容器的区别。


9. 去掉 sudo docker

第一次执行:

docker images

可能遇到:

permission denied while trying to connect to the docker API

这是因为当前用户还没有加入 docker group。

执行:

sudo usermod -aG docker "$USER"

然后退出并重新登录 SSH。

再运行:

docker images

即可正常访问 Docker daemon。

Docker 官方同样提醒:docker group 会给予用户非常高的系统权限,因此只应加入可信用户。Docker Documentation


10. 最终状态

最后这台 Jetson 的容器环境为:

Jetson Orin Nano Super
│
├── Docker Engine 29.9.1
├── Docker Compose 5.6.0
├── Docker Buildx 0.38.0
├── containerd
│
├── NVIDIA Container Toolkit 1.16.2
└── NVIDIA Container Runtime

检查:

docker --version
docker compose version
docker buildx version

systemctl is-active docker

docker info | grep -i -A3 runtime

能够看到:

Runtimes: io.containerd.runc.v2 nvidia runc

即可认为 Docker + NVIDIA Container Runtime 安装完成。


Troubleshooting:本文真正踩到的两个坑

1. nvidia-container 要 1.16.2,但 APT 想装 1.20.1

不要看到更高版本就直接强行安装。

JetPack 对平台组件存在明确的版本依赖。先:

apt-cache policy ...

确认当前 JetPack 所要求的版本,再显式指定对应版本。

本文最终使用:

nvidia-container               6.2.1+b38
nvidia-container-toolkit       1.16.2-1
nvidia-container-toolkit-base  1.16.2-1
libnvidia-container-tools      1.16.2-1
libnvidia-container1           1.16.2-1

2. apt 突然提示 dpkg lock 被占用

不要立刻:

sudo rm /var/lib/dpkg/lock-frontend

更不要上来就:

kill -9

先:

ps -fp <PID>

如果父进程最终是:

/etc/systemd/nv-install-docker.sh

说明 JetPack 正在替你自动安装 Docker。

等它完成即可。


最后

Jetson 上安装 Docker 的关键其实不是 Docker 本身。

真正需要意识到的是:

普通 Ubuntu:
Docker

Jetson:
Docker
+
NVIDIA Container Runtime
+
JetPack / L4T 版本配套

直接照普通 Ubuntu 的 Docker 教程,Docker Engine 本身很可能也能安装成功,但会漏掉 Jetson 真正需要的平台集成。

而 JetPack 6.2.x 这一代已经把流程做得相当自动化:至少本文实际使用的 nvidia-container 6.2.1+b38 会自动触发 Docker CE 安装、启用服务并写入 NVIDIA runtime 配置。

剩下需要人为注意的,反而是版本冲突、不要误杀后台 installer,以及安装后重启 Docker daemon。


参考资料

本文安装流程和排查主要参考以下官方资料:

  • NVIDIA Jetson Orin Nano Developer Kit — Docker Setup
    介绍 Jetson 上安装 Docker、nvidia-container、配置 NVIDIA Container Runtime,以及使用 nvidia-ctk 配置 Docker runtime 的官方流程。
    https://docs.nvidia.com/jetson/orin-nano-devkit/user-guide/latest/setup_docker.html
  • NVIDIA JetPack 6.2 — Install & Setup
    用于确认 JetPack 6.2 / L4T R36.4 系列的软件栈、安装方式和平台版本关系。
    https://docs.nvidia.com/jetson/jetpack/6.2/install-setup/index.html
  • Docker Engine — Install on Ubuntu
    Docker 官方 Ubuntu 安装文档,用于确认 docker-ce、docker-ce-cli、containerd.io、Buildx、Compose 等官方软件包及 ARM64 支持方式。
    https://docs.docker.com/engine/install/ubuntu/
  • Docker Engine — Linux Post-installation Steps
    介绍将用户加入 docker group、无需 sudo 使用 Docker 等常见安装后配置。
    https://docs.docker.com/engine/install/linux-postinstall/
  • NVIDIA Container Toolkit Documentation
    NVIDIA Container Toolkit 的通用官方文档,可用于进一步了解 nvidia-container-runtime、nvidia-ctk 以及 Docker runtime 配置机制。
    https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/