一、ROS的三种镜像
1.1 ROS的官方镜像:osrf/ros
官网:https://hub.docker.com/r/osrf/ros
这个镜像是ROS官方的镜像,包含各个版本的ROS以及ROS2,然而这个镜像无法打开RVIZ和Gazebo,因此不推荐使用该镜像!
为了解决镜像中无法使用RVIZ和Gazebo的问题,衍生出两种解决方法,一种是在镜像中安装图形显卡驱动,如nvidia/opengl,或将图形数据输出如VNC,来显示图形化界面;另一种是通过安装GUI桌面组件来显示图形化界面,如xfce4和LXDE。
1.2 不含桌面组件的ROS镜像
通过nvidia/opengl或VNC来显示图形化界面的优点在于不需要引出额外的桌面环境,镜像较小,缺点是VNC有些图形化的组件仍然会缺失,如运行Gazebo会报ALSA错,并且nvidia/opengl与显卡种类相关,如没有NVIDIA的显卡,就无法使用nvidia/opengl作为图形化驱动。
如果仅是运行代码测试,不深度使用Gazebo,该类镜像还是可以使用的,主要优点就是镜像较小,可以使用这类镜像。
1.3 含桌面组件的ROS镜像
常见的桌面环境,如xfce4,其可以一个提供轻量级桌面环境; LXDE,全名为Lightweight X11 Desktop Environment,也是一个开源桌面环境。
所有的ROS的镜像都是从ubuntu的镜像开始构建,如FROM ubuntu:18.04
,此类镜像是不含GUI桌面组件,添加桌面组件后,即可运行含有GUI界面的程序,不仅仅是RVIZ和Gazebo,因此推荐使用此类镜像作为自己配置的环境。
1.4 分类参考(选读)
ubuntu GUI界面显示的解决方式有三种
三种介绍:
https://www.cnblogs.com/panpanwelcome/p/12877902.html
https://blog.csdn.net/sirobot/article/details/106836332
原理:https://www.cnblogs.com/panpanwelcome/p/12877902.html
1.是通过vnc,可以直接用ubuntu的镜像
vnc是作为中介,把在宿主机打开,所以docker里面不涉及到gui,本质是调用外界gui。
https://blog.csdn.net/zkk9527/article/details/121159353
2.是采用xserver,需要nvidia的镜像
内置驱动,在docker里面打开,把数据流传输出来,本质是在里面打开gui。
3.直接ip传输
https://blog.csdn.net/wzw_mzm/article/details/70916202
二、构建不含桌面组件的ROS镜像
容器要使用NVIDIA图形化界面,必须安装nvidia-container-toolkit
套件,以下操作都是在宿主机上进行
添加nvidia-container-toolkit
的源
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
&& curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
&& curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
安装nvidia-container-toolkit
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
然后安装不同ROS版本
2.1 ROS kinetic版本(ubuntu16.04)
2.1.1 创建Dockerfile文件,构建镜像
kinetic版本主要参考了这位博主:https://blog.csdn.net/zdegrh_2/article/details/102936547
osrf/ros:kinetic
无法运行gazebo和rviz,必须要引入glvnd
构建Dockerfile,才能正常使用其中的RVIZ和Gazebo这种图形化界面。
构建ros的镜像需要从本地copy一个名为10_nvidia.json
的文件到镜像中。
①新建10_nvidia.json
文件:
{
"file_format_version" : "1.0.0",
"ICD" : {
"library_path" : "libEGL_nvidia.so.0"
}
}
②新建Dockerfile
文件:
ARG from
FROM nvidia/opengl:1.0-glvnd-runtime-ubuntu16.04 as glvnd
FROM osrf/ros:kinetic-desktop-full
COPY --from=glvnd /usr/local/lib/x86_64-linux-gnu /usr/local/lib/x86_64-linux-gnu
COPY --from=glvnd /usr/local/lib/i386-linux-gnu /usr/local/lib/i386-linux-gnu
COPY 10_nvidia.json /usr/local/share/glvnd/egl_vendor.d/10_nvidia.json
RUN echo '/usr/local/lib/x86_64-linux-gnu' >> /etc/ld.so.conf.d/glvnd.conf && \
echo '/usr/local/lib/i386-linux-gnu' >> /etc/ld.so.conf.d/glvnd.conf && \
ldconfig
ENV LD_LIBRARY_PATH /usr/local/lib/x86_64-linux-gnu:/usr/local/lib/i386-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
# nvidia-container-runtime
ENV NVIDIA_VISIBLE_DEVICES \
${NVIDIA_VISIBLE_DEVICES:-all}
ENV NVIDIA_DRIVER_CAPABILITIES \
${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics
RUN apt-get update && \
apt-get install -y \
build-essential \
libgl1-mesa-dev \
libglew-dev \
libsdl2-dev \
libsdl2-image-dev \
libglm-dev \
libfreetype6-dev \
libglfw3-dev \
libglfw3 \
libglu1-mesa-dev \
freeglut3-dev \
dbus
③生成镜像
创建好Dockerfile之后,通过docker build命令来创建镜像,该命令首先会上传Dockerfile文件给Docker服务器端,服务器端将逐行执行Dockerfile中定义的指令。
通常建议放置Dockerfile的目录为空目录。另外可以在目录下创建.dockerignore文件,让Docker忽略路径下的文件和目录,这一点与Git中的配置很相似。
通过 -t 指定镜像的标签信息,例如:docker build -t regenzm:first_image .
,注意最后一个.指定的是Dockerfile所在的路径。
docker build . -t ros:kinetic
注意该命令要求,Dockerfile文件名称必须严格为Dockerfile,否则要添加-f选项指定文件名称,如:
docker build -f xx -t ros:kinetic
其中xx为文件名称,如果出现权限问题,则需要新建一个文件夹,把10_nvidia.json
和Dockerfile
文件方进去,重新执行构建命令。
2.1.2 Dockerfile文件解析
整个Dockerfile分为五个部分:
①引入基础镜像
ARG from
FROM nvidia/opengl:1.0-glvnd-runtime-ubuntu16.04 as glvnd
FROM osrf/ros:kinetic-desktop-full
有多个FROM
,以最后一个为准。将NVIDIA的镜像作为别名glvnd。然后进入到ROS官方镜像环境中,从
②拷贝图形化镜像文件
COPY --from=glvnd /usr/local/lib/x86_64-linux-gnu /usr/local/lib/x86_64-linux-gnu
COPY --from=glvnd /usr/local/lib/i386-linux-gnu /usr/local/lib/i386-linux-gnu
COPY 10_nvidia.json /usr/local/share/glvnd/egl_vendor.d/10_nvidia.json
从NVIDIA镜像中拷贝文件x86_64-linux-gnu
和i386-linux-gnu
到ROS官方镜像中对应路径中,把本地新建的文件也拷贝进去(这个文件是NVIDIA官方提供的,具体见https://gitlab.com/nvidia/container-images/opengl/-/tree/ubuntu16.04/glvnd/runtime),这些文件都是图形显示所需的可执行文件。
③链接可执行文件
RUN echo '/usr/local/lib/x86_64-linux-gnu' >> /etc/ld.so.conf.d/glvnd.conf && \
echo '/usr/local/lib/i386-linux-gnu' >> /etc/ld.so.conf.d/glvnd.conf && \
ldconfig
先把配置文件路径保存到.conf文件中,然后链接对应的可执行文件。
④设置环境变量
ENV LD_LIBRARY_PATH /usr/local/lib/x86_64-linux-gnu:/usr/local/lib/i386-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
# nvidia-container-runtime
ENV NVIDIA_VISIBLE_DEVICES \
${NVIDIA_VISIBLE_DEVICES:-all}
ENV NVIDIA_DRIVER_CAPABILITIES \
${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics
设置NVIDIA显卡驱动的环境变量
⑤安装一些包
RUN apt-get update && \
apt-get install -y \
build-essential \
libgl1-mesa-dev \
libglew-dev \
libsdl2-dev \
libsdl2-image-dev \
libglm-dev \
libfreetype6-dev \
libglfw3-dev \
libglfw3 \
libglu1-mesa-dev \
freeglut3-dev \
dbus
其中最后一个包dbus
是图形化显示所必须的包!
2.1.3 拉取镜像命令
docker pull xxx
xhost +
在宿主机上运行显示界面的映射
docker run --gpus all -ti --name ros_kinetic -e DISPLAY --env="QT_X11_NO_MITSHM=1" -v /tmp/.X11-unix:/tmp/.X11-unix ros:kinetic /bin/bash
2.2 ROS melodic版本(ubuntu18.04)
2.2.1 创建Dockerfile文件,构建镜像
melodic版本主要参考了这位博主:https://blog.csdn.net/liuqixuan1994/article/details/114089786
与ros kinetic类似,osrf/ros:kinetic
无法运行gazebo和rviz,必须要引入glvnd
构建Dockerfile,才能正常使用其中的RVIZ和Gazebo这种图形化界面。
①新建Dockerfile文件
# FROM ubuntu:18.04
FROM nvidia/cudagl:10.2-base-ubuntu18.04
LABEL Description="A Dockerfile to setup $RES_NAME:$TAG" Author="liuqixuan" Version="1.0"
# Official sources.list
#ARG sourcelist="http://packages.ros.org/ros/ubuntu"
# Mirrors sources.list
# ARG sourcelist="http://mirrors.ustc.edu.cn/ros/ubuntu/"
ARG sourcelist="http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/"
# ARG sourcelist="http://mirrors.sjtug.sjtu.edu.cn/ros/ubuntu/"
ARG workdir="/root/catkin_ws"
ARG DEBIAN_FRONTEND=noninteractive
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=YES
ENV XDG_RUNTIME_DIR="/tmp/runtime-root"
RUN set -x \
&& apt-get update \
&& apt install apt-transport-https \
&& apt install ca-certificates \
&& apt update \
&& cp /etc/apt/sources.list /etc/apt/sources.list.bak \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse" > /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse" >> /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse" >> /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse" >> /etc/apt/sources.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends apt-utils gnupg2 curl vim git xarclock \
&& sh -c '. /etc/lsb-release && echo "deb \${sourcelist} \${DISTRIB_CODENAME} main" > /etc/apt/sources.list.d/ros-latest.list' \
&& apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 \
&& apt-get update \
&& apt-get install -y ros-melodic-desktop-full \
&& echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc \
&& bash -c '. ~/.bashrc'
RUN apt-get install -y python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential
RUN apt-get install dbus
RUN echo "185.199.111.133 raw.githubusercontent.com" >> /etc/hosts
#RUN rosdep init \
# && rosdep update
#RUN useradd noroot -u 1000 -s /bin/bash \
# && echo "user added!"
#USER noroot
#USER root
#SHELL ["/bin/bash", "-c"]
RUN apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir \${XDG_RUNTIME_DIR} && chmod 700 \${XDG_RUNTIME_DIR} \
&& mkdir \${workdir} \
&& set +x
WORKDIR \${workdir}
ENTRYPOINT ["/bin/bash"]
②构建镜像
docker build . -t ros:melodic
与kinetic版本一样,注意文件名称和权限问题。
③进入镜像
docker run --gpus all -it --name kinetic -e DISPLAY --env="QT_X11_NO_MITSHM=1" -v /tmp/.X11-unix:/tmp/.X11-unix ros:melodic /bin/bash
④修改gazebo报错
构建好的镜像可以打开rviz,但是打开gazebo会报错,[Err] [REST.cc:205] Error in REST request
,此时进入容器的/root目录下(也是~/目录),修改:.ignition/fuel/config.yaml文件:
将
url: [https://api.ignitionfuel.org]
改为
url: [https://api.ignitionrobotics.org]
注意空格对齐,否则也汇报错
⑤gazebo的warning,可以暂时不用管
打开gazebo会提示ALSA 问题,
ALSA是声卡驱动一种,是微软的WSL组件,gazebo中用到了这个,其中无法解决ALSA声卡组件问题,查看了ubuntu的目录,在/dev/snd目录下没有建立相关的文件节点,所以肯定是找不到的,又好像是openal的问题,相当于ubuntu系统没有安装声卡驱动,但是测试gazebo是没有问题的,暂时忽略。
gazebo中ALSA报错分析
https://bbs.csdn.net/topics/390175774
ls /dev/snd
在宿主机里有输出,在docker里面没有。
openal声卡
https://www.cnblogs.com/8335IT/p/12155179.html
wsl问题的issue
https://github.com/microsoft/WSL/issues/3644
https://github.com/microsoft/wslg/issues/634
猜测是docker安装的ubuntu镜像不完整,或者opengl驱动不完整造成的。
2.2.2 Dockerfile文件解析
①基础镜像与ROS软件源设置
# FROM ubuntu:18.04
FROM nvidia/cudagl:10.2-base-ubuntu18.04
LABEL Description="A Dockerfile to setup $RES_NAME:$TAG" Author="liuqixuan" Version="1.0"
# Official sources.list
#ARG sourcelist="http://packages.ros.org/ros/ubuntu"
# Mirrors sources.list
# ARG sourcelist="http://mirrors.ustc.edu.cn/ros/ubuntu/"
ARG sourcelist="http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/"
# ARG sourcelist="http://mirrors.sjtug.sjtu.edu.cn/ros/ubuntu/"
ARG workdir="/root/catkin_ws"
ARG DEBIAN_FRONTEND=noninteractive
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=YES
ENV XDG_RUNTIME_DIR="/tmp/runtime-root"
以NVIDIA的镜像作为基础镜像,该镜像同样是基于ubuntu:18.04构建的,然后打上LABEL,设置一些描述性信息,这里尊重原博主,予以保留。
接着设置ubuntu的ROS软件更新镜像源,换成国内清华源,这样更新ROS较快。
然后创建一个catkin_ws
的目录
ARG DEBIAN_FRONTEND=noninteractive
这条命令意味着在安装软件的时候不需要选择,按照最优配置来进行装,如果不设置此参数,安装软件的过程中有可能需要交互,就会卡着不动。
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=YES
是允许设置APT key,以免报错不让添加。
最后设置运行目录环境参数。
②安装软件
RUN set -x \
&& apt-get update \
&& apt install apt-transport-https \
&& apt install ca-certificates \
&& apt update \
&& cp /etc/apt/sources.list /etc/apt/sources.list.bak \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse" > /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse" >> /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse" >> /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse" >> /etc/apt/sources.list \
&& apt-get update \
&& apt-get install -y --no-install-recommends apt-utils gnupg2 curl vim git xarclock \
&& sh -c '. /etc/lsb-release && echo "deb \${sourcelist} \${DISTRIB_CODENAME} main" > /etc/apt/sources.list.d/ros-latest.list' \
&& apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 \
&& apt-get update \
&& apt-get install -y ros-melodic-desktop-full \
&& echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc \
&& bash -c '. ~/.bashrc'
RUN apt-get install -y python-rosdep python-rosinstall python-rosinstall-generator python-wstool build-essential
RUN apt-get install dbus
RUN echo "185.199.111.133 raw.githubusercontent.com" >> /etc/hosts
Docker容器内需要先执行apt-get update
命令获取软件源才能安装软件,其中apt-transport-https、 ca-certificates是必须的,因为默认的ROS源是http的,但替换用的清华镜像源是https,所以休要额外的安装关于HTTPS的包。
在安装ros的时候,要把ubuntu的镜像源改为清华的,否则有些包就因为网络问题,没法安装上去。把它当成一个ubuntu双系统去对待,修改其sourcelist.txt文件。
然后就是ubuntu18.04常见安装ROS的操作了
apt-utils是apt-get install的包,gnupg2是验证gpg的包,curl来传输网络数据,vim git是常用工具,xarclock是一个gui钟表,用来测试用,也可以不装。
dbus包是x11 server需要的,不装会报错,无法显示图形界面。
最后设置了把github的地址放进去了
③清除缓存,减小镜像体积
RUN apt-get autoremove -y \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir \${XDG_RUNTIME_DIR} && chmod 700 \${XDG_RUNTIME_DIR} \
&& mkdir \${workdir} \
&& set +x容器要使用图形化界面,必须安装`nvidia-container-toolkit`套件,**以下操作都是在宿主机上进行**
##3.1 添加`nvidia-container-toolkit`的源
distribution=IDdistribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
##3.2 安装`nvidia-container-toolkit`
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker
WORKDIR \${workdir}
ENTRYPOINT ["/bin/bash"]
清除一些缓存文件,减小镜像体积,最后设置进入容器的工作目录
2.2.3 拉取镜像命令
docker pull xxx
xhost +
在宿主机上运行显示界面的映射
docker run --gpus all -ti --name melodic -e DISPLAY --env="QT_X11_NO_MITSHM=1" -v /tmp/.X11-unix:/tmp/.X11-unix ros:melodic /bin/bash
2.3 总结
通过NVIDIA的驱动来解决rviz和gazebo可视化显示
0 构建自己的镜像,要引入nvidia的那个镜像,然后安装ROS。(rviz那个报错需要宿主机安装nvidia驱动)
1 安装nvidia docker,并且要在run的时候加上--gpus参数
2 apt-get install dbus,开启x11必须软件包
3 xhost + 运行显示界面的映射
4 运行参数要加上显示设置的参数
docker run --gpus all -ti -e DISPLAY --env="QT_X11_NO_MITSHM=1" -v /tmp/.X11-unix:/tmp/.X11-unix ros:kinetic
--gpus 调用gpu显示gui界面
-it 以交互方式进入到容器中
--rm 退出容器时,会自动删除容器
-e DISPLAY 是开启显示,否则无法显示
--env="QT_X11_NO_MITSHM=1"如果不设置,gazebo无法正常显示
-v /tmp/.X11-unix:/tmp/.X11-unix 显示传输的缓存地址,使用的是X11server的服务
2.4 osrf和NVIDIA的Dockerfile
osrf/ros有自己的dockerfile,在github的最里面
https://github.com/osrf/docker_images/blob/master/ros/melodic/ubuntu/bionic/ros-core/Dockerfile
下面网站分别三cudagl,cuda,opengl的docker镜像,可以在overiew里面看到对应的dockerfile,可以看出,这些镜像都是从ubuntu18.04作为base开始构建。
https://hub.docker.com/r/nvidia/cudagl
https://hub.docker.com/r/nvidia/cuda
https://hub.docker.com/r/nvidia/opengl
三、含桌面组件的ROS镜像
3.1 Docker容器图形界面显示(运行GUI软件)的配置方法种类介绍
Docker显示GUI界面的解决方式有三种
三种介绍:
https://www.cnblogs.com/panpanwelcome/p/12877902.html
3.1.1 通过vnc,可以直接用ubuntu的镜像
vnc是作为中介,把在宿主机打开,所以docker里面不涉及到gui,本质是调用外界gui。
https://blog.csdn.net/zkk9527/article/details/121159353
3.1.2 是采用xserver,需要nvidia的镜像
内置驱动,在docker里面打开,把gui数据流传输出来,本质是在里面打开
3.1.3 直接ip传输
https://blog.csdn.net/wzw_mzm/article/details/70916202
3.1.4 安装桌面组件
常见的桌面环境,如xfce4,其可以一个提供轻量级桌面环境; LXDE,全名为Lightweight X11 Desktop Environment,也是一个开源桌面环境。
LXDE相比xfce4更为齐全,且有声音设备驱动,可以完美打开Gazebo;而xfce4运行gazebo会报ALSA的waring。
用LXDE构建的博客:
https://blog.csdn.net/fafawf/article/details/104474727
用LXDE构建ROS
https://blog.csdn.net/weixin_39752599/article/details/116425034
比较常用的lxde镜像:
https://hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc
其它镜像都是在该基础上进行开发的
用xfce4构建的博客
xfce构建比较简单,
https://blog.csdn.net/lxyoucan/article/details/121679346
高质量的镜像
1泡泡机器人(注意拉镜像的时候,要加上tag,如ros-vnc:kinetic、ros-vnc:melodic)
https://hub.docker.com/r/paopaorobot/ros-vnc
2纯LXDE的ubuntu桌面,不含ROS
https://hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc
https://github.com/ct2034/docker-ubuntu-vnc-desktop/blob/master/Dockerfile(fork了上一个LXDE的repo)
3基于2构建的ROS镜像
https://github.com/lishuwei0424/ros-melodic-docker/blob/main/Dockerfile
https://github.com/Tiryoh/docker-ros-desktop-vnc/blob/master/melodic/Dockerfile
为这些镜像安装ROS中,遇到的ros init和rosdep update问题,解决方法有1直接执行的,2有不执行的,3有拷贝文件过去的(3中的第二个github链接)。
关于rosdep update,官方orsf镜像的操作,没有切换用户,是以root用户执行此命令的
RUN rosdep init && \
rosdep update --rosdistro $ROS_DISTRO
四、分发docker镜像
4.1 离线模式
1.主机A有镜像nginx,版本为v1.0版本。执行命令:
docker save -o nginx:v1.0 /root/nginx.tar
---> 将nginx:v1.0保存为nginx.tar包
2.通过scp命令将nginx.tar包拷贝给主机B。
3.在主机B上执行命令:
docker load -i /root/nginx.tar
---> 从nginx.tar包load为镜像nginx:v1.0
注意:执行docker save nginx:v1.0 -o /root/nginx.tar
命令,如果不加版本v1.0
,会将主机A上所有版本nginx镜像都save到一个nginx.tar包。
4.2 在线模式
注册dockerhub账号,上传上去后,再通过阿里云加速,暂时用不到,建议用离线镜像部署。