Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
X11 in docker on macOS

To forward X11 from inside a docker container to a host running macOS

  1. Install XQuartz: https://www.xquartz.org/
  2. Launch XQuartz. Under the XQuartz menu, select Preferences
  3. Go to the security tab and ensure "Allow connections from network clients" is checked.
  4. Run xhost + ${hostname} to allow connections to the macOS host *
  5. Setup a HOSTNAME env var export HOSTNAME=`hostname`*
  6. Add the following to your docker-compose:
  environment:
  - DISPLAY=${HOSTNAME}:0
  volumes:
  - /tmp/.X11-unix:/tmp/.X11-unix

* It should be noted that steps 4 and 5 can be automated to run everytime XQuartz starts, but that's outside of the scope of this gist

@fapfap69
Copy link

fapfap69 commented Nov 11, 2017

Thanks a lot Sir !
It works fine...

@elehcimd
Copy link

elehcimd commented Mar 21, 2018

it worked for me as well, but after restarting Quartz after step 3

@loadaverage
Copy link

loadaverage commented Mar 27, 2018

Seems that ${hostname} is not correct, should it be ${HOSTNAME} or $(hostname)?
Anyway, I have troubles while trying binding X11 to UNIX socket, network connections works fine.
But it's not so comfortable for me.
UPDATE: nevermind, UNIX sockets are not supported yet
So, xhost or socat (UNIX socket->localhost port) is the only way to go.

@k2973363
Copy link

k2973363 commented Jul 12, 2019

Works well!

@DrSnowbird
Copy link

DrSnowbird commented Sep 20, 2019

For my MacOS docker run to display X11, I need to set up docker run with "-e DISPLAY=host.docker.internal:0" and then it works!

@vmayoral
Copy link

vmayoral commented Oct 29, 2019

+1 to -e DISPLAY=host.docker.internal:0 from @DrSnowbird, it seems that after the last Docker security updates, that form works and previous ones do not anymore.

@xeonqq
Copy link

xeonqq commented Dec 24, 2019

Instead of step 4, I have to do the following:

IP=$(ifconfig en1 | grep inet | awk '$1=="inet" {print $2}')
/usr/X11/bin/xhost +
/usr/X11/bin/xhost + "$IP"

and +1 also to DrSnowbird

@paul-krohn
Copy link

paul-krohn commented Apr 5, 2020

Thanks for this, it really helped me out!

It seems things have moved a bit underneath all this since 2017, so I created an updated version.

@dragon788
Copy link

dragon788 commented Aug 11, 2020

@xeonqq the first line you have allows ANY IP to access your X11 display not just the IP you added on the next line.

@theRealSuperMario
Copy link

theRealSuperMario commented Sep 16, 2020

I created a small example for running firefox inside a docker container here. If this fires up firefox on your mac, you are good to go.

@dozzman
Copy link

dozzman commented Oct 4, 2020

Thanks for this, it really helped me out!

It seems things have moved a bit underneath all this since 2017, so I created an updated version.

For anyone arriving... this link contains the only correctly current version. Steps to follow...

It also helped me understand why the volume mount doesn't do anything and what's really going on.

In short: (with optional explanation)

  1. From the XQuartz preferences, in the security tab, make sure Allow connections from network clients is enabled. Restart XQuartz.

NB: After restarting XQuartz, you can run netstat -an | grep -F 6000 to find that XQuartz has opened port 6000. This is actually how your docker container will be communicating with XQuartz on the host. The volume mount is not (and cannot due to an ongoing issue -- more details in the original link) be used.

  1. In a terminal on the host, run xhost +localhost.

NB: This will allow network X11 connections from localhost only, which is fine. Also if XQuartz is not running, xhost will start it.

  1. Pass -e DISPLAY=host.docker.internal:0 to any docker image you want to forward X to the host.

NB: host.docker.internal is the DNS name which resolves to your host machine from within your docker container. This will get X within the container to connect to port 6000 on your host and communicate with XQuartz -- the volume mount is entirely unused. You can also set the env var directly in the container with bash/Dockerfile/etc.

  1. Run your application.

NB: If all of the above steps were completed successfully, an X window should open on your host which is forwarding from the container. Debugging steps can be checked from the link above.

Much thanks to @paul-krohn for putting together his README which clarified a lot.

@ManuelSchneid3r
Copy link

ManuelSchneid3r commented May 16, 2021

Step 4: I have no xhost on my system. Or do I have to run this in the docker container?

@paul-krohn
Copy link

paul-krohn commented May 16, 2021

xhost is part of XQuartz and on my system is at /opt/X11/bin/xhost. Do you for sure have /opt/X11/bin in your PATH?

@ManuelSchneid3r
Copy link

ManuelSchneid3r commented May 18, 2021

Yes somehow after restarting it was available. Maybe PATH lookup issues.

@DrSnowbird
Copy link

DrSnowbird commented Jul 15, 2021

The latest version of "DrSnowbird/jdk-mvn-py3-x11" already automatically" set up everything for you.

The latest version will automatically do all the necessary X11 setup for you except "the installation of xquartz" (running the 'run.sh' will automatically launch XQuartz).

So, you don't have do anything to run X11 on your host machine regardless macOS, Ubuntu, or CentOS (due to the automation inside run.sh). It is just as simple as below since "run.sh" script automatically does everything for you.

  1. First, "git clone https://github.com/DrSnowbird/jdk-mvn-py3-x11.git"
  2. then, "cd jdk-mvn-py3-x11"
  3. then, "./run.sh" . Then, you should see the "xeyes" X11 application showing up on your desktop.
    Bonus,
  4. try, "./shell.sh" using a new X-terminal, then run "firefox" from command line, you see will Firefox browser popping up on your Desktop.

That's it!

Important: You don't have to do anything setup including xhost, HOSTNAME, etc. It is all automatically done in "run.sh"

  • "run.sh" script that It has everything automation (auto-detect your host's OS) setup for you except that, in macOS, you need to have 'xquartz' installed as the only manual effort when running on macOS - not for other Linux (e.g., Ubuntu, or CentOS).

PS: if you are still having trouble, my recommendation is to use "noVNC" using your web HTML 5 browsers to run as your desktop. You can access your Docker Container's desktop using any HTML 5 web browser. Please see:

@stevenirby
Copy link

stevenirby commented Feb 12, 2022

I couldn't get it working without running it this way. (on an M1 Mac)

docker run -it --env="DISPLAY=host.docker.internal:0" -v /tmp/.X11-unix:/tmp/.X11-unix:rw <image name>

This did NOT work.

-e DISPLAY=host.docker.internal:0

@DrSnowbird
Copy link

DrSnowbird commented Feb 21, 2022

Most likely you need to install XQuartz first on Mac to allow X11 to work to display to your Desktop. However, with the licensing fee requirements to run Docker with Docker-Desktop on Mac, I myself am not using Docker/Docker-Desktop anymore. I am using 100% Linux (Ubuntu/CentOS and other variations) now for all my open-source projects. Hence, I can't help much further now on Mac. There are many blogs that provide alternative Docker solutions.

@ScottFred
Copy link

ScottFred commented Jun 13, 2022

This was great! Thanks for providing this GIST!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment