Skip to content

Instantly share code, notes, and snippets.

@cschiewek
Last active November 6, 2024 12:03
Show Gist options
  • Save cschiewek/246a244ba23da8b9f0e7b11a68bf3285 to your computer and use it in GitHub Desktop.
Save cschiewek/246a244ba23da8b9f0e7b11a68bf3285 to your computer and use it in GitHub Desktop.
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

@marcospgp
Copy link

For those arriving from google like me: 2024 Dockerfile and compose.yaml for MacOS host:

FROM ubuntu:latest

# Install X11 and sample x11 apps
RUN apt-get update && \
    apt-get install -y x11-apps

# Open xclock on startup
CMD ["xclock"]
services:
  gui-app:
    build: .
    environment:
      - DISPLAY=host.docker.internal:0
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix

Before docker compose up, install xquartz and do enable network connections on settings security tab.

@harunkurtdev
Copy link

harunkurtdev commented Jan 23, 2024

Heyoo brotherss,

You can find on the this link,

I find some solution.

apptainer/singularity#5524 (comment)

on the link output

Ekran Resmi 2024-01-24 02 06 19

@jamesjmchugh
Copy link

For those arriving from google like me: 2024 Dockerfile and compose.yaml for MacOS host:

FROM ubuntu:latest

# Install X11 and sample x11 apps
RUN apt-get update && \
    apt-get install -y x11-apps

# Open xclock on startup
CMD ["xclock"]
services:
  gui-app:
    build: .
    environment:
      - DISPLAY=host.docker.internal:0
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix

Before docker compose up, install xquartz and do enable network connections on settings security tab.

I just wanted to post and confirm this worked for me in February 2024 on an m2 macbook. Thank you!

@amura87516
Copy link

For those arriving from google like me: 2024 Dockerfile and compose.yaml for MacOS host:

FROM ubuntu:latest

# Install X11 and sample x11 apps
RUN apt-get update && \
    apt-get install -y x11-apps

# Open xclock on startup
CMD ["xclock"]
services:
  gui-app:
    build: .
    environment:
      - DISPLAY=host.docker.internal:0
    volumes:
      - /tmp/.X11-unix:/tmp/.X11-unix

Before docker compose up, install xquartz and do enable network connections on settings security tab.

I just wanted to post and confirm this worked for me in February 2024 on an m2 macbook. Thank you!

Somehow it didn't work on my M2 MacOS :(

Error: Can't open display: host.docker.internal:0
Screenshot 2024-02-26 at 10 24 40 PM

Any suggestion?

@ldipenti
Copy link

There shouldn't be a need of using "DISPLAY=host.docker.internal:0" and mounting the "/tmp/.X11-unix" socket file. I was able to make this work with just the DISPLAY envvar and enabling network connections and disabling connections auth in XQuartz settings.
Nevertheless, I think the ideal would be to just use the "/tmp/.X11-unix" file instead of network connections. I'm not being able to make this work even though the file seems to be correctly mounted inside the container.

@Tigatok
Copy link

Tigatok commented Apr 5, 2024

@ldipenti FTR I had to include the host.docker.internal:0, in 2024. I'm on a MacBook Pro 2024 m3 version.

Here is a working Dockerfile and Dockercompose:

FROM openjdk:11

# Install necessary packages for X11 or for your app
RUN apt-get update && apt-get install -y \
    libxext6 \
    libxrender1 \
    libxtst6 \
    x11-apps

# Set the working directory
WORKDIR /app

# Copy the source code into the container
COPY src /app/src
COPY dist/lib /app/lib

# Compile the Java application
RUN javac -cp "/app/lib/*" -d /app/bin /app/src/*.java

# Set the DISPLAY environment variable for X11 forwarding
ENV DISPLAY host.docker.internal:0

# Run the compiled Java application
CMD ["java", "-cp", "/app/bin:/app/lib/*", "MainClass"]
version: '3'
services:
  java-app:
    build: .
    image: java-app
    container_name: java-app-container
    environment:
      - _JAVA_OPTIONS="-Dsun.java2d.xrender=false"

I added the _JAVA_OPTIONS stuff cause I was getting some weird color errors on my swing ui.

@NovoG93
Copy link

NovoG93 commented May 24, 2024

Hey all, I am getting these errors when I am running gazebo from docker. Can someone help here? I am using intel i5 Mac and docker version 20.10.8, build 3967b7d

libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
ALSA lib confmisc.c:855:(parse_card) cannot find card '0'
ALSA lib conf.c:5178:(_snd_config_evaluate) function snd_func_card_inum returned error: No such file or directory
ALSA lib confmisc.c:422:(snd_func_concat) error evaluating strings
ALSA lib conf.c:5178:(_snd_config_evaluate) function snd_func_concat returned error: No such file or directory
ALSA lib confmisc.c:1334:(snd_func_refer) error evaluating name
ALSA lib conf.c:5178:(_snd_config_evaluate) function snd_func_refer returned error: No such file or directory
ALSA lib conf.c:5701:(snd_config_expand) Evaluate error: No such file or directory
ALSA lib pcm.c:2664:(snd_pcm_open_noupdate) Unknown PCM default
AL lib: (EE) ALCplaybackAlsa_open: Could not open playback device 'default': No such file or directory
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast

@saikrn112 did you manage to use gazebo/rviz2 or any other gtk based application with docker on your mac?
I am facing the same issues

@R1kk3r
Copy link

R1kk3r commented Jul 8, 2024

Lot of comments here, not always correct. Here is the TL;DR.

Volume?

  volumes:
  - /tmp/.X11-unix:/tmp/.X11-unix

This is useless, Docker Desktop does not support Unix socket (exception made for a very specific SSH case). A very good reading to get all the details https://briefcase.readthedocs.io/en/stable/how-to/internal/x11passthrough.html

The only solution is to use the network via the DISPLAY=host.docker.internal:0.

libGL error?

If you get the following error:

libGL error: failed to load driver: swrast

You can try to indirect rendering by setting the export LIBGL_ALWAYS_INDIRECT=1

X request error?

If you get the following error:

X Error of failed request:  BadValue (integer parameter out of range for operation)
  Major opcode of failed request:  149 (GLX)
  Minor opcode of failed request:  24 (X_GLXCreateNewContext)
  Value in failed request:  0x0
  Serial number of failed request:  25
  Current serial number in output stream:  26

The latest Quartz version are buggy. I downgraded to 2.7.8 and everything works fine.

X connection error?

If you get Error: Can't open display: host.docker.internal:0, try to ping host.docker.internal. If it works, then the network is up and running but somehow Quartz is not listening/accepting the connection. Otherwise, this is a docker network issue. In the former case, you need to make sure the settings in Quartz are configured properly "allow connection + disable authorisation". Make sure to add in xhost and also try to reboot (sometimes, running/killing quartz to many times makes it unable to listen correctly on the port).

In addition, starting/stopping XQuartz multiple times, it might have changed the port number. Run the command sudo lsof -i -P | grep LISTEN | grep :$PORT and make sure you see x11.bin using port 6000. If it uses something else, for example 6001, it means you need to adapt the DISPLAY to DISPLAY=host.docker.internal:1, if it is 6005 you should set to DISPLAY=host.docker.internal:5.

@taylorchu
Copy link

taylorchu commented Sep 29, 2024

@idossha
Copy link

idossha commented Oct 21, 2024

I was stuck on this for a while. Eventually I realized there might be a problem with Xquartz. Indeed after downgrading as suggested by @R1kk3r and following these steps below everything worked fine.

defaults write org.macosforge.xquartz.X11 nolisten_tcp -bool false
export DISPLAY=localhost:0
xhost +localhost
xhost +$(hostname)

Hope that helps.

@devnoname120
Copy link

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