云服务器Docker运行ROS,并通过VNC连接

  • 使用华为云服务器
  • 系统Ubuntu18
  • VNC为x11vnc

安装图形界面

选择Xubuntu界面,占用资源较少,参考链接ubuntu安装gui

  1. 直接安装即可
    sudo apt install xubuntu-core
  2. 安装完成后可能需要启动
    startx

安装并启动x11vnc

开始用的tightvnc,后来发现不能远程启动rviz,报错信息:

[ INFO] [1537648559.395352789]: rviz version 1.12.16
[ INFO] [1537648559.395581867]: compiled against Qt version 5.5.1
[ INFO] [1537648559.395659829]: compiled against OGRE version 1.9.0 (Ghadamon)
[ INFO] [1537648559.835809950]: Stereo is NOT SUPPORTED
[ INFO] [1537648559.836059261]: OpenGl version: 3 (GLSL 1.3).

于是换成x11vnc:
参考链接:Ubuntu18.04 远程命令行下安装并启动x11vnc

  1. 安装
    sudo apt-get install x11vnc
  2. 生成密码
    sudo x11vnc -storepasswd
  3. 编辑启动文
    sudo vim /lib/systemd/system/x11vnc.service 启动文件内容(USERNAME要替换成自己的用户名)
[Unit] 
Description=Start x11vnc at startup. 
After=multi-user.target 
 
[Service] 
Type=simple 
ExecStart=/usr/bin/x11vnc -env FD_XDM=1 -display :0 -auth guess -forever -loop -noxdamage -repeat -rfbauth /home/USERNAME/.vnc/passwd -rfbport 5900 -shared -o /var/log/x11vnc.log 

 
[Install] 
WantedBy=multi-user.target
  1. 另一个窗口启动lightdm
    sudo lightdm
  2. 添加到服务中
sudo systemctl daemon-reload
sudo systemctl enable x11vnc.service
sudo systemctl start x11vnc.service
  1. 验证x11vnc服务
    sudo netstat -an | grep 5900 出现:
tcp        0      0 0.0.0.0:5900            0.0.0.0:*               LISTEN     
tcp6       0      0 :::5900                 :::*                    LISTEN
  1. 远程连接vnc
    接下来就可以在远程客户端vnc连接服务器了,使用TightVNC viewer(注意将IP换成你的云服务器IP地址)

vnc 打开docker浏览器 docker ubuntu vnc_docker

8. 远程连接vnc

目前有个问题,有时候vnc会断连,此时重启服务也不能连接到服务器桌面,于是手动启动x11vnc而不是通过服务启动。新建脚本start_x11vnc.sh,

内容如下:

nohup x11vnc -rfbport 5900 -passwd PASSWORD -create -forever -display :0 -o ~/x11vnc.log & 注意将PASSWARD为设置的密码,可以自定义,连接的时候要使用该密码。然后添加可执行权限:

chmod +x start_x11vnc.sh

运行脚本,x11vnc将在后台运行。

Docker运行ROS

  1. 重要但是很容易忘记的一步
    xhost +

xhost命令是X服务器的访问控制工具,用来控制哪些X客户端能够在X服务器上显示。
xhost +代表关闭访问授权,允许任何主机访问本地X服务器

  1. 拉取镜像
    docker pull ros:melodic-desktop-full
  2. 创建容器并运行(注意将USERNAME换成你的用户名)
sudo docker run -it \
    -e DISPLAY=unix$DISPLAY \
    --env="QT_X11_NO_MITSHM=1" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    -v /home/USERNAME/ros/docker_ros_ws:/home/USERNAME/ros_ws \
    osrf/ros:melodic-desktop-full
  1. 启动master节点(注意是在容器中)
    roscore
  2. 另外打开一个终端,进入刚才的容器,注意把container_id换成真实的id
    sudo docker exec -it container_id bash
  3. 在容器内设置DISPLAY变量(这一步似乎很重要,设置为0,我也不太清楚什么意思)
    export DISPLAY=:0
  4. source一下环境变量(仍然在容器内)
    source ros_entrypoint.sh
  5. 检查是否可以运行rviz(仍然在容器中)
    rviz 若出现rviz窗口,则成功

Docker 挂载文件夹权限问题

上面的第3步:“创建容器并运行”里还有个不足之处:docker默认是以root用户运行容器的,当在容器内新建文件时,文件的所有者是root。而在容器外,我们一般是普通用户,对这些文件是没有权限的。为解决这一问题,可以利用Dockerfile新建镜像,在Dockerfile里添加用户并切换到新添加的用户。

Dockerfile如下:

FROM osrf/ros:melodic-desktop-full

RUN useradd --create-home --no-log-init --shell /bin/bash hitzhang && \ 
    groupadd -g 129 docker && \
    adduser hitzhang sudo && \
    echo "hitzhang:1" | chpasswd

RUN usermod -u 1000 hitzhang && usermod -G 129 hitzhang

WORKDIR /home/hitzhang

USER hitzhang

该Dockerfile添加了名为hitzhang、用户组为docker、uid为1000、gid为129的新用户,并设置进入容器时,自动切换到hitzhang用户,同时切换工作目录到hitzhang的主目录。username、groupname不是很重要,可以随意,但是uid、gid设置成什么呢?

  1. id命令
  2. 设置
    可以看到:uid=1000,gid=129。知道uid和gid就可以将Dockerfile里的id替换,构建镜像。