我在 EndeavourOS 上维护了一个 Ubuntu 20.04 + ROS Noetic 的 x86_64 Distrobox。ROS 编译和命令行节点一直正常,但运行 RViz 时,OpenGL 实际落到了 llvmpipe 软件渲染。
这篇不重复 ROS Noetic 的完整安装过程,重点记录如何在保留现有容器和独立 home 的前提下,先克隆验证,再把容器安全改成 NVIDIA 硬件加速模式。
最终环境:
- 容器名:
ros-noetic - 容器 home:
~/distrobox-homes/ros-noetic - 系统:Ubuntu 20.04.6 LTS / amd64
- ROS:
ros-noetic-desktop-full 1.5.0-1focal.20250521.014741 - 容器 Mesa:21.2.6
- 独显:NVIDIA GeForce RTX 5070 Ti Laptop GPU
- 宿主 NVIDIA 驱动:610.43.02
- OpenGL renderer:NVIDIA / OpenGL 4.6
一、先确认不是设备映射问题
容器可以看到宿主机的 DRI 设备:
distrobox enter ros-noetic -- bash -lc '
ls -l /dev/dri
for d in /dev/dri/card* /dev/dri/render*; do
stat -c "%n mode=%a owner=%U:%G" "$d"
done
'实际存在:
card0
card1
renderD128
renderD129render node 也可以读写。因此问题不是 Distrobox 没有传入 GPU,而是容器里的用户态驱动不认识当前核显。
二、为什么 direct rendering: Yes 仍然可能是软件渲染
宿主机 Intel 核显是 Arrow Lake-S,PCI ID 为 8086:7d67。Ubuntu 20.04 容器里的 Mesa 21.2.6 加载 iris 时会明确报告:
MESA: warning: Driver does not support the 0x7d67 PCI ID.
libGL error: failed to create dri screen
libGL error: failed to load driver: iris随后回退到:
direct rendering: Yes
Device: llvmpipe (LLVM 12.0.0, 256 bits)
Accelerated: no
OpenGL renderer string: llvmpipe (LLVM 12.0.0, 256 bits)所以不能只看 direct rendering: Yes。真正应该检查的是:
OpenGL renderer string- Mesa renderer 下的
Accelerated - 是否出现
llvmpipe、swrast或failed to load driver
为了保持 Ubuntu 20.04 + ROS Noetic 依赖稳定,我没有给容器混装第三方 Mesa/LLVM,而是复用宿主机已经正常工作的 NVIDIA 驱动。
三、验证宿主机 NVIDIA PRIME offload
先在宿主机执行:
nvidia-smi --query-gpu=name,driver_version --format=csv,noheader
__NV_PRIME_RENDER_OFFLOAD=1 \
__GLX_VENDOR_LIBRARY_NAME=nvidia \
glxinfo -B本机结果:
NVIDIA GeForce RTX 5070 Ti Laptop GPU, 610.43.02
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: NVIDIA GeForce RTX 5070 Ti Laptop GPU/PCIe/SSE2
OpenGL core profile version string: 4.6.0 NVIDIA 610.43.02只有宿主机 PRIME offload 正常,才继续改容器。
四、先克隆测试,不直接删除原容器
先停止原容器:
distrobox stop ros-noetic --yes创建独立的测试 home,并克隆现有容器:
mkdir -p ~/distrobox-homes/ros-noetic-nvidia-test
distrobox create \
--clone ros-noetic \
--name ros-noetic-nvidia-test \
--home ~/distrobox-homes/ros-noetic-nvidia-test \
--nvidia \
--additional-flags "--env __NV_PRIME_RENDER_OFFLOAD=1 --env __GLX_VENDOR_LIBRARY_NAME=nvidia --env __VK_LAYER_NV_optimus=NVIDIA_only" \
--yes这里三个环境变量分别负责:
- 启用 NVIDIA PRIME render offload;
- 让 GLX 默认选择 NVIDIA;
- 让 Vulkan 应用优先只枚举 NVIDIA GPU。
首次进入测试容器时,Distrobox 会显示:
Setting up host's nvidia integration... [ OK ]五、验证测试克隆
进入测试容器:
distrobox enter ros-noetic-nvidia-test检查 NVIDIA 驱动和 OpenGL:
nvidia-smi --query-gpu=name,driver_version --format=csv,noheader
glxinfo -B测试克隆的实际输出:
NVIDIA GeForce RTX 5070 Ti Laptop GPU, 610.43.02
direct rendering: Yes
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: NVIDIA GeForce RTX 5070 Ti Laptop GPU/PCIe/SSE2
OpenGL core profile version string: 4.6.0 NVIDIA 610.43.02再启动一次 RViz:
source /opt/ros/noetic/setup.bash
rviz测试时 RViz 持续运行,日志中没有 MESA: warning、libGL error 或 failed to load driver。
六、用验证过的镜像重建同名容器
distrobox create --clone 会把原容器提交为日期标签镜像。例如本次生成的是:
localhost/ros-noetic:2026-07-10确认测试克隆正常后,停止测试容器,把旧容器暂时改名保留:
distrobox stop ros-noetic-nvidia-test --yes
podman rename ros-noetic ros-noetic-no-nvidia-backup用克隆镜像和原来的 home 创建同名容器:
distrobox create \
--image localhost/ros-noetic:2026-07-10 \
--name ros-noetic \
--home ~/distrobox-homes/ros-noetic \
--nvidia \
--additional-flags "--env __NV_PRIME_RENDER_OFFLOAD=1 --env __GLX_VENDOR_LIBRARY_NAME=nvidia --env __VK_LAYER_NV_optimus=NVIDIA_only" \
--yeshome 是宿主机上的独立目录,因此重新指定同一个 --home 后,代码、shell 配置和用户数据仍然保留;/opt/ros 等系统内容则来自刚才验证过的克隆镜像。
七、冷启动后验证 ROS 通信
不要只在第一次进入时验证。停止并重新进入一次:
distrobox stop ros-noetic --yes
distrobox enter ros-noetic再次确认默认 renderer 中没有 llvmpipe:
glxinfo -B | grep -E \
'direct rendering|OpenGL vendor|OpenGL renderer|OpenGL core profile version'然后测试 ROS Master 与话题收发:
source /opt/ros/noetic/setup.bash
roscore >/tmp/ros-noetic-roscore.log 2>&1 &
master_pid=$!
sleep 3
rostopic echo -n 1 /gpu_test &
echo_pid=$!
sleep 2
rostopic pub -1 /gpu_test std_msgs/String \
'data: hello_ros_noetic_nvidia'
wait "$echo_pid"
kill "$master_pid"
wait "$master_pid" 2>/dev/null || true本次实际接收结果:
data: "hello_ros_noetic_nvidia"
---最后确认包数据库没有中断状态:
dpkg --audit八、清理测试环境
同名容器通过冷启动、RViz 和 ROS 通信验证后,再删除测试容器与旧备份:
distrobox rm -f ros-noetic-nvidia-test
podman rm ros-noetic-no-nvidia-backup
rm -rf ~/distrobox-homes/ros-noetic-nvidia-test不要在新容器验证前提前执行这一步。
九、宿主 NVIDIA 驱动升级后
Distrobox 集成的是与宿主机驱动版本匹配的 NVIDIA 用户态库。宿主机升级驱动后,停止并重新进入容器,让 Distrobox 重新执行集成:
distrobox stop ros-noetic --yes
distrobox enter ros-noetic
nvidia-smi
glxinfo -B最终验收标准仍然是 OpenGL renderer string 为 NVIDIA,并且输出中没有 llvmpipe。