While the answer by Jürgen Weigert essentially covers this solution, it wasn't clear to me at first what was being described there. So I'll add my take on it, in case anyone else needs clarification.
First off, the relevant documentation is the X security manpage.
Numerous online sources suggest just mounting the X11 unix socket and the ~/.Xauthority
file into the container. These solutions often work by luck, without really understanding why, e.g. the container user ends up with the same UID as the user, so there's no need for magic key authorization.
First off, the Xauthority file has mode 0600, so the container user won't be able to read it unless it has the same UID.
Even if you copy the file into the container, and change the ownership, there's still another problem. If you run xauth list
on the host and container, with the same Xauthority
file, you'll see different entries listed. This is because xauth
filters the entries depending on where it's run.
The X client in the container (i.e. GUI app) will behave the same as xauth
. In other words, it doesn't see the magic cookie for the X session running on the user's desktop. Instead, it sees the entries for all the "remote" X sessions you've opened previously (explained below).
So, what you need to do is add a new entry with the hostname of the container and the same hex key as the host cookie (i.e. the X session running on your desktop), e.g.:
containerhostname/unix:0 MIT-MAGIC-COOKIE-1 <shared hex key>
The catch is that the cookie has to be added with xauth add
inside the container:
touch ~/.Xauthority
xauth add containerhostname/unix:0 . <shared hex key>
Otherwise, xauth
tags it in a way that it's only seen outside the container.
The format for this command is:
xauth add hostname/$DISPLAY protocol hexkey
Where .
represents the MIT-MAGIC-COOKIE-1
protocol.
Note: There's no need to copy or bind-mount .Xauthority
into the container. Just create a blank file, as shown, and add the cookie.
Jürgen Weigert's answer gets around this by using the FamilyWild
connection type to create a new authority file on the host and copy it into the container. Note that it first extracts the hex key for the current X session from ~/.Xauthority
using xauth nlist
.
So the essential steps are:
- Extract the hex key of the cookie for the user's current X session.
- Create a new Xauthority file in the container, with the container hostname and the shared hex key (or create a cookie with the
FamilyWild
connection type).
I admit that I don't understand very well how FamilyWild
works, or how xauth
or X clients filter entries from the Xauthority file depending where they're run. Additional information on this is welcome.
If you want to distribute your Docker app, you'll need a start script for running the container that gets the hex key for the user's X session, and imports it into the container in one of the two ways explained previously.
It also helps to understand the mechanics of the authorization process:
- An X client (i.e. GUI application) running in the container looks in the Xauthority file for a cookie entry that matches the container's hostname and the value of
$DISPLAY
.
- If a matching entry is found, the X client passes it with its authorization request to the X server, through the appropriate socket in the
/tmp/.X11-unix
directory mounted in the container.
Note: The X11 Unix socket still needs to be mounted in the container, or the container will have no route to the X server. Most distributions disable TCP access to the X server by default for security reasons.
For additional information, and to better grasp how the X client/server relationship works, it's also helpful to look at the example case of SSH X forwarding:
- The SSH server running on a remote machine emulates its own X server.
- It sets the value of
$DISPLAY
in the SSH session to point to its own X server.
- It uses
xauth
to create a new cookie for the remote host, and adds it to the Xauthority
files for both the local and remote users.
- When GUI apps are started, they talk to SSH's emulated X server.
- The SSH server forwards this data back to the SSH client on your local desktop.
- The local SSH client sends the data to the X server session running on your desktop, as if the SSH client was actually an X client (i.e. GUI app).
- The X server uses the received data to render the GUI on your desktop.
- At the start of this exchange, the remote X client also sends an authorization request, using the cookie that was just created. The local X server compares it with its local copy.