Docker is the de facto standard when running containerised applications these days. From simple Hello Worlds to complex, multi-container setups, your application’s deployment could never be simpler.
But what about those applications requiring a graphical front end? Docker is a server-side technology — certainly, you can’t have graphics, right? Or can you? Let’s find out next (TL;DR: yes, you can).
Docker Doesn’t Have Graphics
The term graphics can signify a variety of things in the computer-science and software-development worlds, and certainly, I am not going to try defining it here. With some poetic license, let’s loosely call a desktop application a graphical application: a software requiring a canvas to draw on its user interface.
Obviously, you don’t expect Docker to provide such a canvas to your containers and, rightly so, it does not. In fact, many times you are asked to run a Docker container in headless mode, exactly because of that. So how does one run a desktop application in Docker? Let’s figure that out.
The X Window System (X11, or simply X) is a windowing system for bitmap displays, common on Unix-like operating systems. X provides the basic framework for a GUI environment: drawing and moving windows on the display device and interacting with a mouse and a keyboard.
X requires a server component, allowing interaction within the application to draw their content and get input from the user’s input devices. Applications are completely unaware of where their output will actually be rendered acting as X clients.
To go any further and try out the example below, you need to have an X server running on your PC. If you are on a desktop Linux, you already have one. For macOS, you can download XQuartz, and for Windows, try VcXsrv.
X and Docker Interaction Scenario
Desktop applications will run in Docker and will try to communicate with the X server you’re running on your PC. This can take place either with a Docker engine running on your host or in a Docker engine running on a remote machine. For X, it doesn’t really make a difference — other than some network latency being introduced.
The interaction scenario is depicted in the following figure:
X clients (your desktop applications) do not really need to know much for this communication to take place.
Actually, they don’t need to know anything but the location of the X server and an optional display that they target.
This is denoted by an environmental variable named DISPLAY, with the following syntax:
DISPLAY=xserver-host:0. The number you see after the
: is the display number; for the intents and purpose of this article, we will consider this to be equivalent to “0 is the primary display attached to the X server.”
Let the Fun Begin
Time to run our desktop applications.
Since we’ll be running the desktop application inside a Docker container, whereas the X server will be running on the host machine, we need a way for those two to communicate.
Unfortunately, at the moment, there is no universal, out-of-the-box Docker way to do that. So keep in mind the following settings for macOS, Windows, and Linux:
--net=host -e DISPLAY=:0
Also, remember to have your X server allow remote connections. For Mac and Windows this should be a setting on your X server application whereas, in Linux, you can (temporarily) enable access from all hosts with
No X Windows article can exist without including a reference to the all-time classic xeyes:
docker run --rm -ti -e DISPLAY=docker.for.mac.host.internal:0 fr3nd/xeyes
docker run --rm -ti -e DISPLAY=host.docker.internal:0 fr3nd/xeyes
docker run --rm -ti --net=host -e DISPLAY=:0 fr3nd/xeyes
Gimp allows the quick editing of a photo or drawing when no other tool is available:
docker run --rm -ti -e DISPLAY=docker.for.mac.host.internal:0 jamesnetherton/gimp
docker run --rm -ti -e DISPLAY=host.docker.internal:0 jamesnetherton/gimp
docker run --rm -ti --net=host -e DISPLAY=:0 jamesnetherton/gimp
Quickly fire up an IDE:
docker run --rm -ti -e DISPLAY=docker.for.mac.host.internal:0 psharkey/eclipse
docker run --rm -ti -e DISPLAY=host.docker.internal:0 psharkey/eclipse
docker run --rm -ti --net=host -e DISPLAY=:0 psharkey/eclipse
A Word processor, spreadsheet editor, presentation tool, and database editor:
docker run --rm -ti -e DISPLAY=docker.for.mac.host.internal:0 woahbase/alpine-libreoffice:x86_64
docker run --rm -ti -e DISPLAY=host.docker.internal:0 woahbase/alpine-libreoffice:x86_64
docker run --rm -ti --net=host -e DISPLAY=:0 woahbase/alpine-libreoffice:x86_64
XMind is a mind-mapping and brainstorming tool:
docker run --rm -ti -e DISPLAY=docker.for.mac.host.internal:0 mdwheele/xmind
docker run --rm -ti -e DISPLAY=host.docker.internal:0 mdwheele/xmind
docker run --rm -ti --net=host -e DISPLAY=:0 mdwheele/xmind
Fire-up a throw-away browser so nobody can track you:
docker run --rm -ti -e DISPLAY=docker.for.mac.host.internal:0 jess/firefox
docker run --rm -ti -e DISPLAY=host.docker.internal:0 jess/firefox
docker run --rm -ti --net=host -e DISPLAY=:0 jess/firefox
In this article, we saw how a desktop app can run in Docker, leveraging the power of X Windows. The setup is pretty straightforward and requires nothing more than an X server running in your host.
Interested in Docker? Here are some additional posts you, hopefully, find informative and entertaining:
Build and Push to Docker with Maven
How To Recover From a Failed Automated Docker Hub Build
How To Test Your Automated Builds on Docker Hub
Build Your Docker Images Automatically When You Push on GitHub