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)
-
Install XQuartz via brew
$ brew install --cask xquartz
-
Logout and login of your Mac to activate XQuartz as default X11 server
-
Start XQuartz
$ open -a XQuartz
-
Go to Security Settings and ensure that "Allow connections from network clients" is on
-
Restart your Mac and start XQuartz again`
$ open -a XQuartz
-
Check if XQuartz is setup and running correctly
$ ps aux | grep Xquartz
-
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. -
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. -
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 petedavidson887/xclock:0.0.1
Success, good old XClock should be displayed on your screen :)
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.
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...
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
Thank you! works for me