问题描述
宿主机为ubuntu20.04,使用鱼香ros一键安装melodic版本的docker ros,未安装nvidia显卡驱动前正常使用melodic版的ros:
宿主机安装nvidia显卡驱动后,docker中的ros无法使用rviz等可视化工具,有如下报错:
rviz:RenderSystem:error creating render window:OGRE EXCEPTION(3:RenderingAPIException)
Unable to create a suitable GLXContext in GLXContext:GLXContext at /build/ogre-1.9-B6Q
kmW/ogre-1.9-1.9.0+dfsg1/RenderSystems/GL/src/GLX/OgreGLXContext.cpp (line 61)
ERROR][1689942254.7944979441:Unable to create the rendering window after 100 tries
INFO][1689942254.794503168]:Stereo is NOT SUPPORTED
terminate called after throwing an instance of 'std:logic_error
what():
basic_string::_M_construct null not valid
在后续使用中发现,在Ubuntu22中创建ros-noetic的容器,即使宿主机安装了显卡驱动,docker里面的ros在使用rviz等工具不会报错,但是输入nvidia-smi
会提示找不到命令,且运行rviz显示的llvmpipe
问题分析
参考这篇文章
ubuntu20.04安装NVIDIA驱动后docker中rviz,pcl_viewer等涉及到访问宿主机界面的程序不可用
这篇文章认为问题原因是宿主机和容器中opengl版本不一致,在docker中安装对应宿主机的显卡驱动版本后问题解决,本人经过尝试后问题还是没解决,驱动装好后rviz仍然报错,最后参考这篇文章成功解决。
在docker容器中使用nvidia显卡渲染rviz2界面
就是当前容器没法使用宿主机的gpu资源
解决方法
安装NVIDIA Container Runtime和nvidia-docker2使得容器能够访问和使用宿主机的GPU资源,仍然使用fishros2/ros:melodic-desktop-full
镜像,修改构建容器docker run
指令,加入 gpu设置 使得docker可以使用宿主机的GPU资源,重新构建容器。
1.宿主机安装显卡驱动
参考方法:
使用nvidia-smi
测试驱动是否可用:
2. 安装NVIDIA Container Runtime和 nvidia-docker2
NVIDIA Container Toolkit使用户能够构建和运行GPU加速的容器。该工具包包括一个容器运行库和实用程序,用于自动配置容器以利用NVIDIA GPU。
配置存储库 并更新
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 \
&& \
sudo apt-get update
安装nvidia-docker2
sudo apt-get install -y nvidia-docker2
使用nvidia-ctk
命令配置container runtime
sudo nvidia-ctk runtime configure --runtime=docker
重启docker系统:
sudo systemctl restart docker
运行nvidia cuda 容器进行测试:
ubuntu20.04 可以使用下面指令进行测试,docker会自动从nvidia/cuda
拉取11.0.3-base-ubuntu20.04
镜像,并创建一个运行一次即删除的容器
sudo docker run --rm --gpus all nvidia/cuda:11.0.3-base-ubuntu20.04 nvidia-smi
其他版本ubuntu,可以从docker hub上搜索nvidia/cuda
以ubuntu22为例
sudo docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
测试结果:
-
ubuntu20
-
ubuntu22
3. 创建新容器
使用docker run
命令 创建新容器
使用fishros2/ros:melodic-desktop-full
镜像创建新的容器,fishros2/ros:melodic-desktop-full
是鱼香ros一键安装中选择melodic版本的ros容器使用的镜像
这里可以继续使用该镜像创建新容器,使用如下命令:
sudo docker run -dit \
--gpus all \
-e NVIDIA_DRIVER_CAPABILITIES=all \
--name=melodic_docker2 \
-v /home/yearner:/home/yearner \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v /dev/dri:/dev/dri \
--device=/dev/snd \
--device=/dev/dri/renderD128 \
-e DISPLAY=unix$DISPLAY \
-w /home/yearner fishros2/ros:melodic-desktop-full
其中:
-v
:是把宿主机的目录挂载到容器中,/home/用户名
需要换成自己的用户名--name
:是容器名称,修改为自己的,需要记住后面还要用到
相比鱼香ros的原安装命令 增加了如下命令允许docker使用宿主机的显卡资源
--gpus all \
-e NVIDIA_DRIVER_CAPABILITIES=all \
下面的操作全部仿照鱼香ros一键安装的指令
运行docker 写入ROS的环境变量
docker exec -it melodic_docker2 /bin/bash -c "echo -e '
source /opt/ros/melodic/setup.bash' >> ~/.bashrc"
构建常用指令
这步操作是允许用户只使用容器名对容器进行操作,省去输入docker的原生指令
cd ~/.fishros/bin
sudo touch melodic_docker2
vi melodic_docker2
xhost +local: >> /dev/null
echo "请输入指令控制melodic_docker2: 重启(r) 进入(e) 启动(s) 关闭(c) 删除(d) 测试(t):"
read choose
case $choose in
s) docker start melodic_docker2;;
r) docker restart melodic_docker2;;
e) docker exec -it melodic_docker2 /bin/bash;;
c) docker stop melodic_docker2;;
d) docker stop melodic_docker2 && docker rm melodic_docker2 && sudo rm -rf /home/yearner/.fishros/bin/melodic_docker2;;
t) docker exec -it melodic_docker2 /bin/bash -c "source /ros_entrypoint.sh && roscore";;
esac
newgrp docker
melodic_docker2
是容器名,更换成自己的容器名
输入:wq!
强制保存,右键该文件点击属性,将权限中勾选允许文件作为程序执行
终端中输入容器名 即可正常使用容器
这样不用在容器中安装显卡驱动也可以直接查看到显卡的驱动信息
如果当前容器你已经使用了一段时间,安装了很多必要的ros、python的库和包,不想再重新开荒,个人使用经验:容器中的ros相比系统中直接安装的ros少了一些依赖库,可以将现有的容器打包成镜像,然后通过上述的操作重新构建容器,这样新构建的容器只比原容器多了可以访问宿主机的gpu
4.将已有的docker容器保存为镜像,利用该镜像创建新容器
通过docker export
和docker import
命令
导出容器
docker export 容器id > 压缩包名.tar
容器id 可以通过docker ps -a
查看
会在当前目录下生成一个压缩包既为该容器的快照
导入容器
可以使用 docker import
从容器快照文件中再导入为镜像
cat ros-melodic-docker.tar | docker import - test/ros:melodic-desktop-full
test/ros:melodic-desktop-full
,test为作者 ros 为镜像名 melodic-desktop-full
为标签
使用docker image ls
查看系统里的镜像,快照已经恢复为镜像,大小发生相比原生fishros2/ros
的镜像大了好多
使用恢复的镜像通过docker run
命令创建新容器
sudo docker run -dit \
--gpus all \
-e NVIDIA_DRIVER_CAPABILITIES=all \
--name=melodic_docker2 \
-v /home/yearner:/home/yearner \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v /dev/dri:/dev/dri \
--device=/dev/snd \
--device=/dev/dri/renderD128 \
-e DISPLAY=unix$DISPLAY \
-w /home/yearner test/ros:melodic-desktop-full
直接改使用的镜像名会产生如下报错:
docker: Error response from daemon: No command specified.
See ‘docker run --help’.
运行导入的镜像创建容器,必须要带command
具体的command 可以通过docker ps --no-trunc
命令在导出容器的时候查看
或者使用docker ps -a
command命令为/bin/bash
在docker run 命令 镜像名后面加上/bin/bash
即可,成功
参考资料
创建docker容器报错:Error response from daemon: No command specified
Docker -从入门到实践
docker-菜鸟教程
Ubuntu下 NVIDIA Container Runtime 安装与使用
ubuntu20.04安装NVIDIA-docker
演示视频
来源:B站up主:每天都要笑得超甜
解决ubuntu20.04 安装docker ros melodic 无法打开rviz和gazebo 问题