About the mechanism when displaying the GUI with Docker

Introduction

When I wanted to display the GUI with Docker, I wanted to understand what was happening, so I made a note. I referred to ROS Tutorial, but I think the same applies to other containers.

By the way, How to display GUI with VNC and browser is recommended because it is easy. However, here I will describe the behavior when using the X window system.

X window system A window system often used in UNIX-like operating systems. It consists of a server and a client, and communicates using the X protocol. Since the protocol version is 11, since 1987, the system is also called X11, or simply X. The X implementation is Xorg, which is used by many Linux distributions.

The X server controls input / output devices such as displays, mice, and keyboards. Originally, X itself was created with the intention of displaying and operating the window of a program that runs over the network on the display at hand, with the image of the X server being local and the X client being remote. Of course it works even if the X client is local.

Reference: Mechanism and settings of X Window System

Mechanism to display GUI with Docker

--Socket
In order to display the GUI with Docker, the X client in the Docker container needs to communicate with the host X server. If the X server and X client are on the same computer, this is usually a UNIX-domain socket. The socket file is under `/tmp/.X11-unix```, and you can access it to communicate with the X server. You can access it from inside the container by mounting `/tmp/.X11-unix``` when starting the Docker container.

--Environment variable DISPLAY
Specify the X server to which the X client connects with `DISPLAY```. The format is ``` hostname: displaynumber.screennumber```. For example, ``` localhost: 0.0```. However, the hostname and screen number can be omitted, so in this case `: 0may be used. If you add --env =" DISPLAY "``` to docker run, the environment variables of the host will be reflected in the container.

Easy way

Then, not only should I set /tmp/.X11-unix and `` `DISPLAY``` in docker run, but authentication is required to communicate with the X server. Normally the root user cannot access the X server, but you can do it on the host by doing the following: However, this is not recommended for security reasons.

$ xhost +local:root

A little safer way

You can access it by making the UID and GID of the Docker container the same as the host. For example, set the --user option as follows:

$ docker run -it --rm \
    --user=$(id -u $USER):$(id -g $USER) \
    --env="DISPLAY" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    osrf/ros:melodic-desktop-full

However, in a Docker image that does not have a user other than root set, it will be ``` I have no name!` ``. You can mount the required directory as shown below to have the same user name as the host in the container.

$ docker run -it \
    --user=$(id -u $USER):$(id -g $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:melodic-desktop-full

How to quarantine

If the Docker image has a user other than root, it seems that the UID and GID should be set to the same as the host. For example, create the following Dockerfile.

FROM osrf/ros:melodic-desktop-full

#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

Build the Dockerfile with the following command and start it to become a container that can display the GUI. (In the Tutorial that I referred to, it was necessary to create and mount an X authentication file, but it worked without it in my environment)

$ docker build -t hoge .
$ docker run -it --rm \
    --env="DISPLAY" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    -user="myNewUserName" \
    hoge

reference

in conclusion

I got a little better understanding of docker and GUI. However, I'm a little sick because the area around X authentication moved without touching it ...

Recommended Posts

About the mechanism when displaying the GUI with Docker
About the behavior when doing a file map with java
Simulate the simplex method with GUI
When requested access to the resource is denied when pushing with Docker
Let's specify the version when using docker
About Docker
Problems I was addicted to when building the digdag environment with docker
Change the layout when rotating with onConfigurationChanged
About Docker
Image flew when updating Docker with WSL2
Getting started with the JVM's GC mechanism
About specifying the validity period when saving the cache in Redis with Spring Cache
About the treatment of BigDecimal (with reflection)
About the mechanism of the Web and HTTP
About the speed when fetching values from HashMap
Make Volume faster when using Docker with vscode.
[CentOS 8] About the work when rebuilding ConoHa VPS
About the method
About Docker capacity
About the package
Error encountered with notes when deploying docker on rails
[First team development ③] Share the development environment created with Docker
About Class loading and initialization when the JVM starts
When I bcrypt with node + docker, I got an error
Display ROS application on Docker with GUI on host side
Talk about going through the source path when delombok
Switch the display screen when hovering the tab with jQuery
Debug the VSCode + Docker + PHP development environment with XDebug.
When the server does not start with rails s