X11 forwarding of GUI app in Docker container

David Brough picture David Brough · Feb 11, 2017 · Viewed 9.1k times · Source

I am currently trying to run some GUI apps in docker containers. I have been trying the ones by jessie frazelle at github. However I can build the images (or get from docker hub) and run them without any visible errors but, the windows don't display (i cant see the app).

I am running Docker version 1.13.1 on Ubuntu 16.04

The image is created from:

FROM debian:stretch
MAINTAINER Jessie Frazelle <[email protected]>

RUN apt-get update && apt-get install -y \
    libreoffice \
    --no-install-recommends \
    && rm -rf /var/lib/apt/lists/*

ENTRYPOINT [ "libreoffice" ]

the run command i am using is below:

docker run -d \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v /etc/localtime:/etc/localtime \
    -e DISPLAY=unix$DISPLAY 
    -v $HOME/Documents:/root/Documents \
    -e GDK_SCALE \
    -e GDK_DPI_SCALE \
    --name libreoffice \
    jess/libreoffice

After searching many sources, I can see that the above should work, andmost people are saying that the following lines are required in the run command,

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

but still I cant get the window to display.

  1. How can I get this to work?
  2. What am I fundamentally missing?

Any help would be appreciated.

Answer

Salem picture Salem · Feb 11, 2017

To be able to communicate with the X server, the user that runs the app has to be allowed to communicate with the X server. So I think you have two options:

  1. Allow the user you have in the container to connect to the X server. If your app is run with user root inside the container, you can use:

    $ xhost +SI:localuser:root

(I don't know the security implications of this, but root should be able to connect either way...)

  1. Add a user in the container that matches your user session. If the user you are using in the host system has UID = 1000, you can create a dummy user inside the container:

    $ useradd -u 1000 my_user

And then use that user to run your app inside the container. This doesn't require any change in the accepted hosts (as user 1000 is already capable of connection).

Looking at the two options, the second seems better, because it does not require any change in the host system, and if you need to use this container in other systems that the main user could not match UID=1000, you can make the container receive the correct uid from an env var, and then set up the correct user (useradd + chown program files).