Docker for GUI-based environments? Docker for GUI-based environments? docker docker

Docker for GUI-based environments?


Currently this question is not answered, but it is very highly ranked on Google. The other answers are mostly correct, but with some caveats that I have learned the hard way, and I would like to save others trouble.

The answer given by Nasser Alshammari is the simplest (and fastest) approach to running GTK applications inside a Docker container - simply mount the socket for the X server as a Docker volume and tell Docker to use that instead.

docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY TheImage

(I would also recommend passing the -u <username-within-container> flag, as running X11 applications as root does not always work, and is generally not recommended, especially when sharing sessions).

This will work for applications such as xterm, as well as GTK-based applications. For example, if you try this with Firefox (which is GTK-based), it will work (note that if you are already running Firefox on the host, it will open a new window in the host rather than open a new instance of Firefox from within the container).

However, your answer asks about PyQT specifically. It turns out that Qt does not support sharing of X sessions in this way (or at least does not support it well).

If you try running a QT-based application this way, you will probably get an error like the following:

X Error: BadAccess (attempt to access private resource denied) 10  Extension:    140 (MIT-SHM)  Minor opcode: 1 (X_ShmAttach)  Resource id:  0x12dX Error: BadShmSeg (invalid shared segment parameter) 148  Extension:    140 (MIT-SHM)  Minor opcode: 5 (X_ShmCreatePixmap)  Resource id:  0xb1X Error: BadDrawable (invalid Pixmap or Window parameter) 9  Major opcode: 62 (X_CopyArea)  Resource id:  0x2c0000dX Error: BadDrawable (invalid Pixmap or Window parameter) 9  Major opcode: 62 (X_CopyArea)  Resource id:  0x2c0000d

I say "probably" because I have not tested this approach with enough Qt applications to be sure, or dug into the Qt source code enough to figure out why this is not supported. YMMV, and you may get lucky, but if you are looking to run a Qt-based application from within a Docker container, you may have to go the "old-fashioned" approach and either

  1. Run sshd within the container, turn on X11 forwarding, and then connect to the container using ssh -X (more secure) or ssh -Y (less secure, used only if you fully trust the containerized application).

  2. Run VNC within the container, and connect to it from the host with a VNC client.

Between those two options, I would recommend the first, but see which works best for your situation.


There are many solutions to have GUI apps running in a docker container. You can use SSH, or VNC for instance. But they add some overhead and delay. The best way that I found is just to pass in the file used by the X server in the host machine as a volume to the container. Like this:

docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY TheImage

Then all your GUI apps will run from container.

Hope This helps!


I managed to run xeyes in a container and see the "window" in a X server running outside of the container. Here's how:

I used Xephyr to run a nested X Server. This is not necessary, but most linux desktops do not allow running remote apps on them by default (here's how to "fix" this on ubuntu).

Install Xephyr:

$ sudo apt-get install xserver-xephyr

Run Xephyr:

$ Xephyr -ac -br -noreset -screen 800x600 -host-cursor :1

This creates a new 800x600 window, which acts as a X server.

Find an "external" address of your machine. This is where the X server is running:

$ ifconfigdocker0   Link encap:Ethernet  HWaddr 56:84:7a:fe:97:99            inet addr:172.17.42.1  Bcast:0.0.0.0  Mask:255.255.0.0          inet6 addr: fe80::5484:7aff:fefe:9799/64 Scope:Link          UP BROADCAST MULTICAST  MTU:1500  Metric:1          RX packets:133395 errors:0 dropped:0 overruns:0 frame:0          TX packets:242570 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:9566682 (9.5 MB)  TX bytes:353001178 (353.0 MB)lo        Link encap:Local Loopback            inet addr:127.0.0.1  Mask:255.0.0.0          inet6 addr: ::1/128 Scope:Host          UP LOOPBACK RUNNING  MTU:65536  Metric:1          RX packets:650493 errors:0 dropped:0 overruns:0 frame:0          TX packets:650493 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:0           RX bytes:2506560450 (2.5 GB)  TX bytes:2506560450 (2.5 GB)wlan0     Link encap:Ethernet  HWaddr c4:85:08:97:b6:de            inet addr:192.168.129.159  Bcast:192.168.129.255  Mask:255.255.255.0          inet6 addr: fe80::c685:8ff:fe97:b6de/64 Scope:Link          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1          RX packets:6587370 errors:0 dropped:1 overruns:0 frame:0          TX packets:3716257 errors:0 dropped:0 overruns:0 carrier:0          collisions:0 txqueuelen:1000           RX bytes:7405648745 (7.4 GB)  TX bytes:693693327 (693.6 MB)

Don't use 127.0.0.1! You can use any of the others. I'll use 172.17.42.1.

Create a Dockerfile with the following content:

FROM ubuntuRUN apt-get updateRUN apt-get install -y x11-appsCMD ["/usr/bin/xeyes"]

Build it:

$ docker build -t xeyes .

And run it:

$ docker run -e DISPLAY=172.17.42.1:1.0 xeyes

Note, that I'm setting the DISPLAY environment variable to where I want to see it.

You can use the same technique to redirect the display to any X server.