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?

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
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)

  • This solution worked for me. Apparently it was enough to just copy .Xauthority file to docker container without need to restart it. – Nikolay Frick Oct 15 '18 at 20:50
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.