docker ros - maohaihua/ros_study GitHub Wiki

https://answers.ros.org/question/191070/compile-roscore-for-arm-board/ https://blog.csdn.net/dddxxxx/article/details/82973576

https://blog.csdn.net/jacka654321/article/details/83035415

https://blog.csdn.net/Chenming_Hnu/article/details/60469410

https://blog.csdn.net/Chenming_Hnu/article/details/74737263

http://wiki.ros.org/docker/Tutorials/GUI http://wiki.ros.org/docker/Tutorials/Docker

https://hub.docker.com/_/ros/

https://blog.csdn.net/xihuanzhi1854/article/details/81673196

https://docs.docker.com/install/linux/docker-ce/ubuntu/

https://forums.docker.com/t/communication-between-containers-and-wider-world/24295/7

docker常用命令

docker load -i ./xxx.tar : 将tar包导入为本地镜像

docker ps :列出所有正在运行的容器

docker image ls :列出所有的镜像

docker start :启动容器

docker stop :暂停容器

docker rm :删除容器

docker run -it :启动容器

Install using the repository

Before you install Docker CE for the first time on a new host machine, you need to set up the Docker repository. Afterward, you can install and update Docker from the repository. Set up the repository

Update the apt package index:

$ sudo apt-get update

Install packages to allow apt to use a repository over HTTPS:

$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

Add Docker’s official GPG key:

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Verify that you now have the key with the fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88, by searching for the last 8 characters of the fingerprint.

$ sudo apt-key fingerprint 0EBFCD88
    
pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) <[email protected]>
sub   rsa4096 2017-02-22 [S]

Use the following command to set up the stable repository. To add the nightly or test repository, add the word nightly or test (or both) after the word stable in the commands below. Learn about nightly and test channels.

    Note: The lsb_release -cs sub-command below returns the name of your Ubuntu distribution, such as xenial. Sometimes, in a distribution like Linux Mint, you might need to change $(lsb_release -cs) to your parent Ubuntu distribution. For example, if you are using Linux Mint Tessa, you could use bionic. Docker does not offer any guarantees on untested and unsupported Ubuntu distributions.

    x86_64 / amd64
    armhf
    arm64
    ppc64le (IBM Power)
    s390x (IBM Z)

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

Install Docker CE

Update the apt package index.

$ sudo apt-get update

Install the latest version of Docker CE and containerd, or go to the next step to install a specific version:

$ sudo apt-get install docker-ce docker-ce-cli containerd.io

    Got multiple Docker repositories?

    If you have multiple Docker repositories enabled, installing or updating without specifying a version in the apt-get install or apt-get update command always installs the highest possible version, which may not be appropriate for your stability needs.

To install a specific version of Docker CE, list the available versions in the repo, then select and install:

a. List the versions available in your repo:

$ apt-cache madison docker-ce

  docker-ce | 5:18.09.1~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
  docker-ce | 5:18.09.0~3-0~ubuntu-xenial | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
  docker-ce | 18.06.1~ce~3-0~ubuntu       | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
  docker-ce | 18.06.0~ce~3-0~ubuntu       | https://download.docker.com/linux/ubuntu  xenial/stable amd64 Packages
  ...

b. Install a specific version using the version string from the second column, for example, 5:18.09.1~3-0~ubuntu-xenial.

$ sudo apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING> containerd.io

Verify that Docker CE is installed correctly by running the hello-world image.

$ sudo docker run hello-world

This command downloads a test image and runs it in a container. When the container runs, it prints an informational message and exits.

Docker CE is installed and running. The docker group is created but no users are added to it. You need to use sudo to run Docker commands. Continue to Linux postinstall to allow non-privileged users to run Docker commands and for other optional configuration steps. Upgrade Docker CE

To upgrade Docker CE, first run sudo apt-get update, then follow the installation instructions, choosing the new version you want to install.

Using X server

X server is a windowing system for bitmap displays, common on linux operating systems. There are several ways one can connect a container to a host's X server for display. A brief description and tradeoffs for each method below:

The first listed is simple, but unsecure
The second is safer, but non-isolated
The third is isolated, but not as portable
The fourth is isolated, works remotely, but is slow. 

The simple way

The simple way is expose your xhost so that container can render to the correct display by reading and writing though the X11 unix socket.

docker run -it
--env="DISPLAY"
--env="QT_X11_NO_MITSHM=1"
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw"
osrf/ros:indigo-desktop-full
rqt export containerId=$(docker ps -l -q)

Above, we made the container's processes interactive, forwarded our DISPLAY environment variable, mounted a volume for the X11 unix socket, and recorded the container's ID. This will fail at first and look something like this, but that's ok:

No protocol specified rqt: cannot connect to X server unix:0

We can then adjust the permissions the X server host. This is not the safest way however, as you then compromise the access control to X server on your host. So with a little effort, someone could display something on your screen, capture user input, in addition to making it easier to exploit other vulnerabilities that might exist in X.

xhost +local:root # for the lazy and reckless

If you are concerned about this (as you should be), you have at least two options. The first is to run

xhost -local:root

after you are finished using the containerized GUI, this will return the access controls that were disabled with the previous command.

A better option is opening up xhost only to the specific system that you want, for instance if you are running a container on the local host's docker daemon with container's ID stored to the shell variable containerId

xhost +local:docker inspect --format='{{ .Config.Hostname }}' $containerId docker start $containerId

This will add the container's hostname to the local family's list of permitted names.

The safer way

A another way is to use your own user's credentials to access the display server. This involves mounting additional directories:

docker run -it
--user=$USER
--env="DISPLAY"
--volume="/etc/group:/etc/group:ro"
--volume="/etc/passwd:/etc/passwd:ro"
--volume="/etc/shadow:/etc/shadow:ro"
--volume="/etc/sudoers.d:/etc/sudoers.d:ro"
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw"
osrf/ros:indigo-desktop-full
rqt

Some applications expect a home directory for the user in order to save and read configuration files, so if you attempt to use them without such a directory existing in the container's filesystem, you may receive warnings or errors.

You could chose to go one step further by mounting your own home directory into the container. This allows you access to local config file for your local user, maintaining the same username, password and file permissions.

docker run -it
--user=$USER
--env="DISPLAY"
--workdir="/home/$USER"
--volume="/home/$USER:/home/$USER"
--volume="/etc/group:/etc/group:ro"
--volume="/etc/passwd:/etc/passwd:ro"
--volume="/etc/shadow:/etc/shadow:ro"
--volume="/etc/sudoers.d:/etc/sudoers.d:ro"
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw"
osrf/ros:indigo-desktop-full
rqt

This last bit how ever removes quite a few layers of separation between what runs in the container and the environment of the host, and is thus not as isolated. So by means of convenience and security, one can lose some aspects of isolation, and other useful properties of repeatability, reducibility, and portability if not careful.

The isolated way

There is another way to emulate the same technique with the previous method but in a more isolated manner. We can do this with some modifications to the original image by creating a user with uid and gid matching that of the host user. This is an example of what you may need to add to the docker file, or simalurly run and commit in the container:

#Add new sudo user ENV USERNAME myNewUserName RUN useradd -m $USERNAME &&
echo "$USERNAME:$USERNAME" | chpasswd &&
usermod --shell /bin/bash $USERNAME &&
usermod -aG sudo $USERNAME &&
echo "$USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/$USERNAME &&
chmod 0440 /etc/sudoers.d/$USERNAME &&
# Replace 1000 with your user/group id usermod --uid 1000 $USERNAME &&
groupmod --gid 1000 $USERNAME

You may need to change the number 1000 for the uid and gid to mach that of your host's user.

The next step is to make a X authentication file with proper permissions and mount this to a volume for the container to use. Here is an example of a run command doing just this:

XSOCK=/tmp/.X11-unix XAUTH=/tmp/.docker.xauth touch $XAUTH xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -

docker run -it
--volume=$XSOCK:$XSOCK:rw
--volume=$XAUTH:$XAUTH:rw
--env="XAUTHORITY=${XAUTH}"
--env="DISPLAY"
-user="myNewUserName"
osrf/ros:indigo-desktop-full
rqt

Now the container is predominantly isolated with only read and write access to X authentication and socket file. The drawback of all this with is that some user specific configuration now resides the image itself, and thereby making it less portable. Should a different user, even on the same host machine, wish to use the same image, they will need to: start an interactive terminal session with the container, change the uid and gid to match their own, commit the container to a new image, and launch the desired GUI container from that one instead. Doing this back and forth also adds needless layers to your image, so introspecting the changins in an image would become a noisy affair.

There are clever ways to get around this, such as making a new user with the same uid and gid at runtime. This take a bit more entrypoint scripting and machinery, but can provide a more portable solution plus remaining just as isolated. An excellent example of this is docker-browser-box.

A non-official tool tries to make it simple and easy-to-use: docker-ros-box. This tool enables you to create a docker container of the ROS distribution you want (based on the desktop-full package) and adds simple scripts to use it. It should also support hardware acceleration.

The ssh way

One of the first ways used to view GUI within containers was done using basic X11 forwarding using an ssh connection. This is bit more involved, as the number of moving parts increases.

We'll need a ssh installed and a running dedicated daemon within each container we launch. This also works against a bit of Docker zen in keeping one container limited to one process, as the daemon adds more dependencies and consumes additional resources.

We'll also need to specify what ports to map/expose for the container, and not to mention passwords or keys on both sides if we want to be secure about things. Its a bit fragile, as every time you spin a container from the same image, you may receive a different IP, an address you need to query Docker for, or look up from inside the container each time. Frame rates will be slow as the display is piped through the local network interface, and not a unix socket, rendering it unfavorable for high bandwidth imagery or user interfaces that deteriorate due to lag.

On the plus side, this does afford you the use of shell access and graphical interfaces within the container even when viewing from a remote client and/or different operating system. But perhaps such efforts could be also applied host's display itself (i.e. VNC), and resort to simpler methods above for connecting the containers to the host's display server. This would most likely depend on how you see your application being used, and what level of effort you'd be willing to put forth in using it.

A good example here has a detailed set instruction on how to enable X11 forwarding using Docker containers: Docker Desktop over SSH

Using VNC

Another common way of viewing graphical interfaces as well as virtual desktops with containers was done early on using Virtual Network Computing (VNC) protical. If low frame rates are not an issue, and you'd prefer a full desktop like view of a container's display, then using VNC may be a suitable option. Granted, it'll take much of the same upfront setup effort as using X11 forwarding with ssh, but you may gain better frame rates thanks to available color compressions and display downsampling settings.

You'll need to install a VNC server inside the image and make sure it starts and that the proper ports are exposed when you launch the container. At this point the container is basically running it's own X server, so it'll have quite a few additional processes running inside at this point. On the plus side, VNC clients are widely available and quite mature on multiple platforms, including phones, so connecting to VNC session is rather easy.

Here is a good example on how to enable VNC server in Docker containers: docker-ubuntu-vnc-desktop

And here you can find an image with kinetic-desktop-full installation accesible via VNC: https://hub.docker.com/r/ct2034/vnc-ros-kinetic-full/

Using Wayland

Using Mir

Using Audio

Alsa Audio

Pulse Audio

Troubleshooting

A few topics to note

The image you use should include all the graphical and display dependencies you require for runtime.
Qt can be a bit buggy in rendering interfaces when used in this way. If you get an error like this:

X Error: BadAccess (attempt to access private resource denied) 10
  Extension:    130 (MIT-SHM)
  Minor opcode: 1 (X_ShmAttach)
  Resource id:  0x3800003

You may need to include

 --env="QT_X11_NO_MITSHM=1"

in your docker run parameters to set the environmental flag to force Qt to show properly. 

Refs: http://olivier.barais.fr/blog/posts/2014.08.26/Eclipse_in_docker_container.html https://github.com/sameersbn/docker-browser-box https://github.com/jfrazelle/dockerfiles/tree/04454ac147edd99c40e42e0117d5c8e0539f5fca https://github.com/pierrekilly/docker-ros-box

⚠️ **GitHub.com Fallback** ⚠️