Docker or Podman for running GUI application?

Hi,
I want to run a GUI app like GIMP for example.

With very simple Dockerfile like,


FROM ubuntu:18.04
RUN apt update && apt upgrade -y && apt install -y -q gimp
CMD "gimp"]

On docker I have to do something like

xhost +local:docker 

To let the app display on my screen.
This is a security concern because somebody else can look at my screen.

While other method exist, I think it is too much work or a bit janky like using VNC.

Does Podman offer better security to run GUI app, how can I use it?

Thank you.

No need to use xhost, mount the xauth cookie / X11 socket instead. To make it secure and simpler, see the x11-docker project.

Podman rootless does not require the container runtime to run as root, so by definition it is more secure for any kind of workload. Running a GUI app is the same as docker though.

Hi, I follow a tutorial that use xauth here: https://www.tutorialspoint.com/running-gui-applications-on-docker-in-linux

I tried it and get avogadro to run without using xhost.

Adapting from the link I give above, this is my dockerfile.


FROM ubuntu:18.04

# Install dependencies
RUN apt-get -y update
RUN apt-get -y install xauth firefox avogadro

#Expose a port number
EXPOSE 8887
RUN xauth add localhost.localdomain/unix:0  MIT-MAGIC-COOKIE-1  c9dd5d2e4182e151a3be39db02679bb9
CMD "avogadro"]

The xauth displayname protocolname hexkey is from host I get from xauth list on the host.
I run the container with

sudo docker run --rm -ti --net=host -e QT_X11_NO_MITSHM=1 -e DISPLAY=$DISPLAY -v /tmp/.X11-unix avogadro

I would like to know if there are security implication here?
Does exposing my container port 8887 bad?
While it work, xauth complain about xauth: file /root/.Xauthority does not exist, is it a problem?

Thank you.

It’s the first time I’ve seen embedding the xauth cookie in the image, that’s a unnecessary burden. You should mount the local xauth cookie in the docker run line. Because by default the cookie matches a hostname, either you’ll have to extract and build a temporary xauth cookie file on the host with FamilyWild, or more simple make the container hostname match the host.

Since you’re running docker, you should run with an unprivileged user, using root inside a container running on a rootful engine is a bad practice, because it equates to root outside the container although with fewer privileges.

Regarding exposing a port from the container, that’s what usually one has to do to access a service inside the container. I can’t tell in this specific case. But since you’re running with net=host the container is already on the host network, so that doesn’t make any sense.

I tried adding this to docker run.

--volume="$HOME/.Xauthority:/root/.Xauthority:rw"

But I don’t have .Xauthority in my home folder. I’m on openSUSE TW, I have never messed with .Xauthority before, does openSUSE not include this file by default?

Location of Xauthority depends on display manager and today name of this file is often random, generated each time Xserver is started. Clients should check value of $XAUTHORITY environment variable.

The simplest and most obvious workaround is to copy (content of) this file in fixed location before starting your container. Then your container can be configured to access this fixed location.

I found it.
kev@localhost:~> echo $XAUTHORITY
/run/user/1000/xauth_JHqaHi

But I’m a bit lost on the second part, do you know if there are tutorial that I can follow?

Are you referring to something like this? The answer by Jürgen Weigert?
https://stackoverflow.com/questions/16296753/can-you-run-gui-applications-in-a-docker-container

I just did this monstrosity to run avogadro in 1 liner.


docker run -d --rm --name avogadro -it -e QT_X11_NO_MITSHM=1 -e DISPLAY=$DISPLAY -v ~/dockersave:/home/savefile -v /tmp/.X11-unix:/tmp/.X11-unix:ro avogadro; docker exec avogadro xauth add $DISPLAY . 0c9101e701a06492089ac35fa19f84ab && docker exec avogadro avogadro

Not sure if it any better than the first one.

The issue is that, with the above command, the container does not stop itself when I close the gui app.

Edit: Huh, I dont know why but I don’t need the third part,


docker run -d --rm --name avogadro -it -e QT_X11_NO_MITSHM=1 -e DISPLAY=$DISPLAY -v ~/dockersave:/home/savefile -v /tmp/.X11-unix:/tmp/.X11-unix:ro avogadro; docker exec avogadro xauth add $DISPLAY . 0c9101e701a06492089ac35fa19f84ab

With the above, the container close it self now.

Update, I use awk to get the key instead of manually copying it.

docker run -d --rm --name avogadro -it -e QT_X11_NO_MITSHM=1 -e DISPLAY=$DISPLAY -v ~/dockersave:/home/savefile -v /tmp/.X11-unix:/tmp/.X11-unix:ro avogadro; docker exec avogadro xauth add $DISPLAY . $(xauth list|awk 'FNR == 1 {print $3}')

Good you figured it out. For reference, I mentioned the project https://github.com/mviereck/x11docker. Knowing how to achieve this with bare docker commands is nice, but this project makes it much easier for many other cases, like sharing other system resources.

That’s a race between the container entrypoint and the docker exec. The first process startup takes so long that the xauth command is able to complete before the main process / X libs reads the x11 cookie. It might work most of the time, but the usual way to do it is to mount the cookie file instead, so no docker exec is needed. OTOH the approach you used would be helpful to re-use the container across reboots.

How do I mount the cookie file? I’m not sure what it meant.

I will also try x11docker out

It’s like you’ve done earlier, but because you used a hardcoded path instead of $XAUTHORITY, it failed. Then it depends on how your display manager is generating the cookie. On TW sddm is generating an entry with FamilyWild:

$ xauth list
myhostname/unix:0  MIT-MAGIC-COOKIE-1  03265ea28d9868b2e9d8d4948dd3a3aa
#ffff##:0  MIT-MAGIC-COOKIE-1  03265ea28d9868b2e9d8d4948dd3a3aa 

Because of the “#ffff#” entry, it should just work inside the container.

If the local .Xauthority doesn’t contain a FW entry, then you’ll either need to set the container hostname to match the host, or generate a new cookie file with FW. x11docker takes care of all this.

I could use awk to replace hardcode hex key like this.

docker run -d --rm --name xreader -e QT_X11_NO_MITSHM=1 -e DISPLAY=$DISPLAY -v ~/dockersave:/home/savefile -v /tmp/.X11-unix:/tmp/.X11-unix:ro xreader && docker exec xreader xauth add $DISPLAY . $(xauth list|awk 'FNR == 1 {print $3}') 

Awk take the output of the xauth list and take only the hexkey. But the race thing you mention still occur.
Anyway, I will just try x11docker.

I tried x11docker.
I works well without much work, also come with gui, very nice.
The strange thing I found is, I need to install openbox in the docker image and my host machine for the app to have proper size and window border. Is this because x11docker isolate the app from accessing my host wm?

x11docker uses most secure settings by default. It tries not to use the host display, which can be exploited by insecure software. You can review all dependencies here: https://github.com/mviereck/x11docker/wiki/Dependencies#dependencies-of-feature-options and capabilities: https://github.com/mviereck/x11docker/wiki/X-server-and-Wayland-Options