Use Ubuntu and other distributions as Docker containers
X Window
Graphical applications can initially cause problems for Docker, but this is easily solved. The trick for classic X applications (not Wayland) is to pass the /tmp/.X11-unix/
directory and the $DISPLAY
environment variable into the container. You can talk an older version of the gedit Gnome editor into working by creating a custom image named oldgedit
(see the "Building an Image with Dockerfile" box).
Building an Image with Dockerfile
In Docker, you can use prebuilt images from Docker Hub, but you can also create customized images. To do this, you need to start a container, make changes to the running system, and create a new image from the changed state with the docker commit
command.
There is also an alternative approach that works without interaction with a running container. You can write what is known as a Dockerfile containing the instructions for building the image. It starts with a FROM
line that specifies a (preexisting) base image, which you then modify with the appropriate commands. For example, you could create an image based on Ubuntu 14.04 using the Dockerfile from Listing 9. You would create this in an otherwise empty folder named Dockerfile
.
Following FROM
, there is the image name like the one you used with docker run
. In the example, this is ubuntu:14.04
for the oldest version of Ubuntu available on Docker Hub. What then follows are three RUN
lines with commands that Docker executes in an Ubuntu 14.04 container created temporarily for this purpose. The two calls to apt
install the gedit package; useradd
creates a non-privileged user named user with a user ID of 1000. The USER
line specifies that all further steps are run with the user ID 1000. This is followed by a CMD
line that specifies the command to run later on at container startup time.
Now, to create an image named oldgedit
using this image recipe, just run the docker build -t oldgedit .
command in the folder containing the Dockerfile. When typing, make sure that the last parameter of the command is a single dot – it stands for the current directory. Docker then executes the instructions from the Dockerfile in a fully automated process. If everything works, the new oldgedit
image will be available afterwards.
Listing 9
Dockerfile
FROM ubuntu:14.04 RUN apt update RUN apt install -y gedit RUN useradd -m user USER 1000 CMD gedit
The oldgedit
image is not configured to start the /bin/bash
shell, but to directly launch the gedit editor. It does this with normal user rights, that is, not as root, but as a user with a user ID of 1000. When you try to start a container now by typing
docker run -it --rm oldgedit
you will see some error messages ending with cannot open display. The program cannot access an X server and therefore cannot open a window.
The X server running on the host creates a special socket type file named X0
below /tmp/.X11-unix/
where applications can contact it. In addition to X0
, there may be other entries here (X1
, X2
, and so on) if multiple X servers are active. The X server to display program windows is determined by the $DISPLAY
environment variable. It typically contains a value of :0
.
Then pass the contents of the variable and access to the sockets in /tmp/.X11-unix/
to the container using the -e DISPLAY
and -v /tmp/.X11-unix:/tmp/.X11-unix
options (Listing 10), allowing gedit to run. Because the home directory is additionally mapped to /home/user/
in the container, gedit should also be able to open and edit files (Figure 5).
Listing 10
X11
$ docker run -it --rm -e DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix \ -v $HOME:/home/user oldgedit
Wayland
Current versions of Ubuntu use Wayland as the successor to the X Window System with Wayland providing a compatibility layer that allows X applications to run on it. Genuine Wayland programs do not run on X. One example is the foot
terminal program, which you can install on Ubuntu by typing sudo apt install foot
. If you launch foot
in a Wayland session, a terminal window appears. If you try the same thing in an X session, a lengthy error message appears, ending with failed to connect to wayland; no compositor running? goodbye.
Wayland uses different sockets and files to provide access to the Wayland server. The socket file is /run/user/1000/wayland-0
instead of /tmp/.X11-unix/X0
, and instead of $DISPLAY
, the variable $XDG_RUNTIME_DIR
contains relevant information such as the folder name /run/user/1000/
. You need to pass both into the container with options similar to those for X, as Listing 11 shows. waylandtest
is just the name of another test image. Support for X and Wayland can also be combined if a Wayland server is running. In this case, you need to pass both sockets and both environment variables into the container.
Listing 11
Wayland
$ docker run -it --rm -e XDG_RUNTIME_DIR -v $HOME:$HOME -v /run/user/1000/wayland-0:/run/user/1000/wayland-0 waylandtest
Conclusions
Docker containers offer a practical alternative to VMs, saving both time and computing resources. With many applications, it's worth learning how to use Dockerfiles to build your own images. You don't always need to start from scratch and can use an image from Docker Hub as a basis, which you configure to meet your needs. Things start to get more exciting when you use a whole series of containers at the same time. Then advanced topics such as container network configuration and orchestration with tools such as Kubernetes [7] start to emerge.
Infos
- "Comparing VirtualBox and VMware Workstation Player" by Thomas Leichtenstern, Linux Magazine, issue 204, November 2017, https://www.linux-magazine.com/Issues/2017/204/VirtualBox-vs.-VMware
- "Run Virtual Machines in Gnome Boxes" by Christoph Langner, Linux Magazine, issue 221, April 2019, https://www.linux-magazine.com/Issues/2019/221/Gnome-Boxes
- Docker: https://www.docker.com
- LXC: https://linuxcontainers.org
- Proxmox: https://pve.proxmox.com/wiki/Main_Page
- Docker Hub: https://hub.docker.com
- Kubernetes: https://kubernetes.io/docs/concepts/overview/
« Previous 1 2 3
Buy this article as PDF
(incl. VAT)