Run GUI Applications in a Docker Container

Deepak Sharma
3 min readJun 9, 2021

First it’s important to understand what Docker actually does. A Docker “container” is a form of encapsulation which seems to be superficially similar to a virtual machine. Unlike a virtual machine, containers share the same Linux kernel as their host system.

The next component is the X Window System. X Servers such as Xorg provide the fundamental graphical capabilities of Unix systems. GUI applications can’t render without an X Server available. (Alternative windowing systems, such as Wayland, are available — we’re focusing on X in this article.)

Trying to run an X Server in Docker is theoretically possible but rarely used. You’d need to run Docker in privileged mode (--privileged) so it could access your host’s hardware. Starting the server would try to claim your video devices, usually resulting in loss of video output as your host’s original X server gets its devices yanked away.

A better approach is to mount your host’s X Server socket into the Docker container. This allows your container to use the X Server you already have. GUI applications running in the container would then appear on your existing desktop.

Why Run GUI Apps in Docker?

Running a GUI program in Docker can be a useful technique when you’re evaluating a new piece of software. You can install the software in a clean container, instead of having to pollute your host with new packages.

This approach also helps you avoid any incompatibilities with other packages in your environment. If you need to temporarily run two versions of a program, you can use Docker to avoid having to remove and reinstall the software on your host.

Forwarding An X Socket to A Docker Container

Providing a Docker container with access to your host’s X socket is a straightforward procedure. The X socket can be found in /tmp/.X11-unix on your host. The contents of this directory should be mounted into a Docker volume assigned to the container. You’ll need to use the host networking mode for this to work.

You must also provide the container with a DISPLAY environment variable. This instructs X clients – your graphical programs – which X server to connect to. Set DISPLAY in the container to the value of $DISPLAY on your host.

What is X Server:

X server is a windowing system for bitmap displays, common on Linux operating systems.

The X11 server (usually Xorg these days) communicates with clients like xterm, firefox, etc via some kind of reliable stream of bytes. A Unix domain socket is probably a bit more secure than a TCP socket open to the world, and probably a bit faster, as the kernel does it all, and does not have to rely on an ethernet or wireless card.

You can encapsulate all this configuration in one docker-compose.yml file:

version: "3"services:
app:
image: my-app:latest
build: .
environment:
- DISPLAY=${DISPLAY}
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
network_mode: host

Next, you need to create a Dockerfile for your application. Here’s an example that runs the Firefox web browser:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y firefox
CMD ["/usr/bin/firefox"]

Now build and run the image:

docker-compose build
docker-compose up

A new Firefox window should appear on your desktop! The Firefox instance will run within the container, independently of any other open Firefox windows. The container will share your host’s X socket, so the containerised Firefox still shows up on your desktop.

Handling X Authentication

Inside the Docker container, install the xauth package. Then run xauth add, passing the token you copied in the previous step.

$ apt install -y xauth 
$ xauth add <token>
$ xauth list

Your container should now successfully authenticate to the X Server.

To run a Firefox instance, simply type “firefox” inside the bash. You will find that the Firefox browser pops up on your local machine even though it is running inside the Docker Container. Using a similar process, you can run almost any user interface application inside Docker Containers and access it on your local machine.

Thanks for reading…….

--

--