Forward X11 over an SSH connection to container's host?

4

4

I'd like to run a containerized GUI application from a remote machine.

I don't want to solve this problem by adding an ssh host to the container because

  • I already have access to the host machine over SSH
  • It adds unnecessary overhead
  • It makes the container non-portable between remote and local use

I can already successfully run GUI apps on the host, but not from within the container. These are the steps I've taken so far:

Host

  • xauth + (not for long term, but useful for eliminating possible problems)
  • docker-user with uid 501000 on host == docker-user with uid 1000 in container via namespace feature
  • .Xauthority file copied to docker-user home folder

Dockerfile

  • Based on alpine
  • Installs xauth and, for testing purposes, xterm
  • Creates docker-user with proper uid/gid

docker-compose

  • Environment variable DISPLAY forwarded in
  • Volume /home/docker-user/:/home/docker-user/:ro to provide .Xauthority cookie
  • Volume /tmp/.X11-unix:/tmp/.X11-unix:ro to provide X11 socket access
  • Runs command su - docker-user -c "export DISPLAY=$DISPLAY && xterm"
    • su used to run as docker-user
    • DISPLAY forwarded into su context

Unfortunately, this is not yet enough. While xterm on the host OS connects to my local X server without issue, xterm in the container says Xt error: Can't open display: localhost:10.0.

I've confirmed that "localhost:10.0" is correct, localhost exists in the container's /etc/hosts, and the cookie and socket are making it through with the right permissions.

What else could possibly be going wrong?

M-Pixel

Posted 2017-04-24T04:08:46.640

Reputation: 204

Answers

5

It looks like you're doing all of the same stuff I'm doing EXCEPT you're sharing the .Xauthority at the time of container creation. That means if you ever ssh -X into your machine after creating the container the .Xauthority will not be valid anymore. You can't ssh -X from another terminal into the same machine and go back and use the .Xauthority, ssh -X changes the .Xauthority every time for the most recent terminal. I've only got it to work by copying the .Xauthority every time I ssh -X into my machine and try and share the screen with my container.

note: I'm sharing a device and a machine id because I was forwarding a webcam output

1.Create the container and tell xhost to allow forwarding from container id:

sudo docker run -it -d \
    --net=host \
    --env="DISPLAY" \
    --env="QT_X11_NO_MITSHM=1" \
    --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
    --device="/dev/video0:/dev/video0" \
    --volume="/path/to/your/sharedDockerFiles:/root/sharedDockerFiles" \
    --volume="/etc/machine-id:/etc/machine-id" \
    yourdockerrepo/image:tag \
    bash
export containerId=$(docker ps -l -q)
sudo xhost +local:`sudo docker inspect --format='{{ .Config.Hostname }}' $containerId`
sudo docker start $containerId

2.Copy .Xauthority from host home to sharedDockerFiles directory:

sudo cp ~/.Xauthority /path/to/your/sharedDockerFiles

3.Start and attach your container

4.Copy the .Xauthority in your shared folder to your container home

sudo cp /root/sharedDockerFiles/.Xauthority ~/

5.(necessary once): Edit container's /etc/ssh/ssh_config under Host * to include:

   ForwardX11 yes
   X11Forwarding yes

6.Restart your container and reattach and run GUI app

7.If you still have problems, make sure $DISPLAY variable in the container is the same as the host's

echo $DISPLAY #do this in the container
exit
echo $DISPLAY #do this in the host, should be the same as container's
#if they aren't equal, start container and:
export DISPLAY= #put the output of your host's $DISPLAY variable here

pale bone

Posted 2017-04-24T04:08:46.640

Reputation: 166

1

Copy .Xauthority in container at the beginning of ssh session before using GUI:

sudo docker exec -i container_name bash -c 'cat > ~/.Xauthority' < ~/.Xauthority

Then, you can pass DISPLAY if using 'docker exec'. E.g. to open new bash:

sudo docker exec -it --env="DISPLAY" container_name bash

2 more possible causes for error: (in addition to accepted answer)

  • basic: You don't have ssh server or xauth in container (for ubuntu run 'apt install openssh-server xauth')

  • sneaky one: If your container hostname is different than the one from host (e.g. set via -h badge in 'docker run') you'll get the error and you have to deal with that (e.g. set the same hostname or add cookie to xauth)

Jure S

Posted 2017-04-24T04:08:46.640

Reputation: 11

This solution worked for me. Apparently it was enough to just copy .Xauthority file to docker container without need to restart it. – Nikolay Frick – 2018-10-15T20:50:29.427

0

Let's start docker with --net=host option. It makes the container to see the same network stack of the host.

For example,

docker run --net=host --rm -ti -u myid -e DISPLAY="$DISPLAY" -v /tmp/.X11-unix:/tmp/.X11-unix image:tag BINARY

psh

Posted 2017-04-24T04:08:46.640

Reputation: 1