Skip to content

Instantly share code, notes, and snippets.

@sorny
Last active October 11, 2024 04:57
Show Gist options
  • Save sorny/969fe55d85c9b0035b0109a31cbcb088 to your computer and use it in GitHub Desktop.
Save sorny/969fe55d85c9b0035b0109a31cbcb088 to your computer and use it in GitHub Desktop.
X11 forwarding with macOS and Docker

X11 forwarding on macOS and docker

A quick guide on how to setup X11 forwarding on macOS when using docker containers requiring a DISPLAY. Works on both Intel and M1 macs!

This guide was tested on:

  • macOS Catalina 10.15.4
  • docker desktop 2.2.0.5 (43884) - stable release
  • XQuartz 2.7.11 (xorg-server 1.18.4)
  • Macbook Pro (Intel)

and

  • macOS Ventura 13.1
  • docker desktop 4.15.0 (93002)
  • XQuartz 2.8.4
  • Mac Studio (M1)

Step-By-Step Guide

  1. Install XQuartz via brew

    $ brew install --cask xquartz

  2. Logout and login of your Mac to activate XQuartz as default X11 server

  3. Start XQuartz

    $ open -a XQuartz

  4. Go to Security Settings and ensure that "Allow connections from network clients" is on

    alt XQuartz Security Stettings

  5. Restart your Mac and start XQuartz again`

    $ open -a XQuartz

  6. Check if XQuartz is setup and running correctly

    $ ps aux | grep Xquartz

  7. Ensure that XQuartz is running similar to this: /opt/X11/bin/Xquartz :0 -listen tcp

    :0 means the display is running on display port 0. Important is that its not saying –nolisten tcp which would block any X11 forwarding to the X11 display.

  8. Allow X11 forwarding via xhost

    $ xhost +

    This allows any client to connect. If you have security concerns you can append an IP address for a whitelist mechanism.

    Alternatively, if you want to limit X11 forwarding to local containers, you can limit clients to localhost only via

    $ xhost +localhost

    Be ware: You will always have to run xhost + after a restart of X11 as this is not a persistent setting.

  9. Time to test X11 forwarding

    Pull the following docker container, set the DISPLAY env and run it...

    $ docker pull sshipway/xclock
    $ docker run -e DISPLAY=docker.for.mac.host.internal:0 sshipway/xclock
    

Success, good old XClock should be displayed on your screen :)

alt XClock

Conclusion

Your Mac is now an unsecured remote X11 server on the network, be aware of this! Stop XQuartz and X11 if you don't need it.

If you want a Docker container or actually any unix client to use your Mac as X11 server, simply set the DISPLAY env variable to your ip-address and display-port. For Docker containers, you can pass the DISPLAY variable via -e DISPLAY=ip:display-port or enter the container and set the DISPLAY env accordingly.

FAQs

Error: Can't open display: <ip>:0 → what to do?

Ensure you ran xhost + If error is still present, ensure XQuartz is allowing network connections. If cli-arg –nolisten tcp is set it wont allow any outside connections...

Error: No protocol specified. → what to do?

When you login through some kind of a display manager, a MIT-MAGIC-COOKIE-1 authentication cookie is created and written to your hosts ~/.Xauthority file. That file is read by X11 clients and the cookies available there are used to authenticate the connections. Thanks to @LevZaplatin for pointing out a workaround: Map your hosts ~/.Xauthority file into your docker container via -v ~/.Xauthority:/root/.Xauthority Applied to the XClock sample above:

$ docker run -v ~/.Xauthority:/root/.Xauthority -e DISPLAY=docker.for.mac.host.internal:0 sshipway/xclock 
@kennyparsons
Copy link

Reviving this old thread. Any way to run a window manager over x11? Something simple like openbox. When i try to run openbox, I get:

> docker run --rm -it -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=host.containers.internal:0 --cap-add SYS_ADMIN x11home
Openbox-Message: A window manager is already running on screen 0

which makes sense. But I can't wrap my head around how to have another window manager running over x11/xquartz.

@ZhangxiJesseFeng
Copy link

Following your tutorial, I used the following to launch the docker:

docker run --platform linux/amd64 --net=host -e DISPLAY=docker.for.mac.host.internal:0 -v ${PWD}:/output -w /output --rm -it rietveld:0.9 /bin/bash

The goal is to run an application's GUI that is installed in the Docker: /Maud/Maud.sh. I had to install 2 java X-term dependencies "libxtst6" and "libxrender1". After this, when attempting to launch the Maud GUI, the process does not return and nothing is opened. At the time of typing this, it has been 5 minutes, which is unusually long for launching this application, even considering the architecture differences and VM effects. Any suggestions would be appreciated! Thanks!

@fishnux
Copy link

fishnux commented Oct 11, 2024

For those running into an issue with the xclock container due to some container image deprecation warning, here's an alternative one:
docker run -e DISPLAY=docker.for.mac.host.internal:0 petedavidson887/xclock:0.0.1

[DEPRECATION NOTICE] Docker Image Format v1 and Docker Image manifest version 2, schema 1 support is disabled by default and will be removed in an upcoming release. Suggest the author of docker.io/sshipway/xclock:latest to upgrade the image to the OCI Format or Docker Image manifest v2, schema 2. More information at https://docs.docker.com/go/deprecated-image-specs/

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