Docker Containers That Can X-11 / Headless X-11
We go over Docker X-11 / headless docker and show 5 recipes to make it work!
If you need GUI access to docker - here is quick guidance on how to do it!
- Docker Containers are effectively small 'virtual computers' that run inside other VM's or servers. They are game changing technology!
- Effectively you have two options. A. port your Xauthority files into the container and use the local X-11 system, or B. Run a full X-11 host inside the container itself.
- Finally we put out 5 good Dockerfile recipes that are tailored and explain X-11 setups!
This is used in Linux where you want to access GUI via the system. This is powerful because you can ssh into a remote machine and access GUI applications, but then go one farther where you can X-11 into a remote system, into a remote container and access a gui application!
To start X-11 immediately inside a Docker container, clarify the intended setup, as the approach differs significantly based on whether the X server runs on the host (most common for GUI forwarding) or inside the container (typically for headless or isolated environments).
1. Most Common Case: Forward GUI Applications from Container to Host X-11 Server
In this scenario, the container runs X-11 clients (graphical applications), while the host provides the X-11 server. Applications display on the host desktop immediately upon launch, provided the container has proper access.
Host preparation (run once before starting the container):
- Allow local connections (temporary and convenient for testing):
xhost +local:docker
For better security, grant access only to a specific container after it starts (using its hostname or ID).
Docker run command example (for a simple GUI test like xclock or Firefox):
docker run -it --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
--net=host \
ubuntu:latest \
bash -c "apt-get update && apt-get install -y x11-apps && xclock"
Key flags explained:
-e DISPLAY=$DISPLAY: Passes the host's display variable (usually:0or:0.0).-v /tmp/.X11-unix:/tmp/.X11-unix:rw: Mounts the host's X11 Unix socket so clients inside the container can connect.--net=host: Ensures network resolution of the display (often required for reliable connections).
For production or repeated use, include X authority handling:
- Mount your
~/.Xauthorityfile and setXAUTHORITYenvironment variable, or copy the magic cookie into the container.
If running as non-root, match user/group IDs with --user $(id -u):$(id -g) and ensure the container user has access to the mounted socket.
This setup allows X11 clients to start immediately when the application launches—no additional server startup inside the container is needed.
2. Headless Case: Run a Full X-11 Server Inside the Container
If the host is headless (no graphical desktop) or you require complete isolation (X server runs entirely inside the container), use a virtual framebuffer such as Xvfb combined with a VNC server (e.g., x11vnc) for remote access.
Example Dockerfile snippet:
FROM ubuntu:latest
RUN apt-get update && apt-get install -y \
xvfb \
x11vnc \
x11-xserver-utils \
fluxbox \ # or another lightweight window manager
&& rm -rf /var/lib/apt/lists/*
# Optional: Create a startup script
COPY <<EOF /start-x11.sh
#!/bin/bash
Xvfb :99 -screen 0 1920x1080x24 &
export DISPLAY=:99
fluxbox &
x11vnc -display :99 -forever -nopw -listen 0.0.0.0 -xkb &
wait
EOF
RUN chmod +x /start-x11.sh
CMD ["/start-x11.sh"]
Build and run:
docker build -t x11-headless .
docker run -d -p 5900:5900 x11-headless
- Connect via VNC client to
localhost:5900. - X11 starts immediately via the entrypoint script. Adjust screen resolution and window manager as needed.
- For even simpler headless testing, run
Xvfb :99 -screen 0 1024x768x24 &followed byexport DISPLAY=:99inside the container.
This method ensures an X11 session initializes right at container startup.
3. Full Desktop Environments Inside Docker
For complete desktop sessions (e.g., XFCE, GNOME), consider specialized tools:
- x11docker: A convenient wrapper that handles X11, GPU acceleration, sound, and more without manual configuration. Install it on the host and run
x11docker your-image. - Pre-built images with VNC/noVNC for browser access.
Additional Recommendations and Troubleshooting
- Permissions: If you encounter "cannot open display" errors, verify the socket mount,
DISPLAYvalue, and X authority. Runxhost +temporarily on the host for debugging. - Privileged mode: Use
--privilegedsparingly (or--device /dev/drifor GPU) only when hardware acceleration is required. - Docker Desktop: On non-Linux hosts (macOS/Windows), native X11 socket mounting is limited or unavailable. Use XQuartz (macOS) or WSLg (Windows) with appropriate network adjustments.
- Security: Avoid broad
xhost +in production; prefer user-specific grants or SSH X11 forwarding for remote scenarios. - Performance: For GPU-intensive apps, add
--gpus alland appropriate device mounts.
If these steps do not align with your exact environment (e.g., specific base image, remote host, or requirement for Xorg instead of Xvfb), please provide additional details such as the host OS, whether the container needs to run clients or a server, and the target application. This will allow a more tailored configuration.
Recipe 1: Minimal Ubuntu Base with Basic X11 Client Applications
This Dockerfile starts from a clean Ubuntu image, installs the minimal X11 client libraries and the x11-apps package (providing test utilities such as xclock and xeyes). No window manager or server is included because the container acts solely as an X11 client. The image is kept lightweight for rapid iteration.
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
x11-apps \
xauth \
&& rm -rf /var/lib/apt/lists/*
CMD ["xclock"]
How it works
The container receives the host’s DISPLAY environment variable and the /tmp/.X11-unix socket at runtime. The xauth package provides the X11 authentication utilities, while x11-apps supplies the demonstration binaries. Nothing runs automatically inside the container beyond the specified CMD; X11 forwarding is enabled entirely by the docker run flags.
Docker run example (Linux host)
xhost +local:docker
docker run -it --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
--net=host \
minimal-x11
Recipe 2: Ubuntu with Lightweight Window Manager (Fluxbox)
This recipe extends Recipe 1 by installing Fluxbox, a minimal window manager. It is useful when you need a simple desktop environment inside the container while still forwarding the entire session to the host X server.
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
fluxbox \
x11-apps \
xauth \
&& rm -rf /var/lib/apt/lists/*
COPY <<EOF /start-x11.sh
#!/bin/sh
fluxbox &
exec "$@"
EOF
RUN chmod +x /start-x11.sh
ENTRYPOINT ["/start-x11.sh"]
CMD ["xclock"]
How it works
The entrypoint script launches Fluxbox in the background before executing the CMD. This provides a minimal windowing context without starting an X server inside the container. The host X server still handles rendering.
Docker run example
xhost +local:docker
docker run -it --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
--net=host \
x11-fluxbox
Recipe 3: Firefox Browser with X11 Forwarding
This Dockerfile installs Mozilla Firefox and the required X11 dependencies. It demonstrates a real-world graphical application that benefits from X11 forwarding.
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
firefox \
xauth \
&& rm -rf /var/lib/apt/lists/*
CMD ["firefox"]
How it works
Firefox is an X11 client; once the container receives the host’s display socket, it renders directly on the host desktop. The image contains only the browser and its X11 runtime dependencies.
Docker run example
xhost +local:docker
docker run -it --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
--net=host \
x11-firefox
Recipe 4: OpenGL-Enabled Image with Mesa Drivers
This recipe adds hardware-accelerated OpenGL support via Mesa for applications requiring 3D rendering (e.g., glxgears). It is suitable for graphics-intensive clients.
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
mesa-utils \
libgl1-mesa-glx \
x11-apps \
xauth \
&& rm -rf /var/lib/apt/lists/*
CMD ["glxgears"]
How it works
Mesa provides software and hardware OpenGL rendering inside the container. For true GPU acceleration on the host, the docker run command must also mount the host’s GPU devices (shown below). The X11 socket forwarding remains identical to previous recipes.
Docker run example (with GPU passthrough)
xhost +local:docker
docker run -it --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
--net=host \
--device /dev/dri \
x11-opengl
Recipe 5: Headless X11 Server (Xvfb) with x11vnc for Remote Access
This recipe runs a complete X11 server inside the container using Xvfb (virtual framebuffer) and exposes the session via VNC. It is ideal for headless hosts or CI environments where no host X server is available.
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
xvfb \
x11vnc \
x11-apps \
fluxbox \
xauth \
&& rm -rf /var/lib/apt/lists/*
COPY <<EOF /start-x11.sh
#!/bin/sh
Xvfb :99 -screen 0 1920x1080x24 &
sleep 1
fluxbox -display :99 &
x11vnc -display :99 -forever -nopw -listen 0.0.0.0 -xkb -shared &
wait
EOF
RUN chmod +x /start-x11.sh
EXPOSE 5900
ENTRYPOINT ["/start-x11.sh"]
How it works
At container startup the entrypoint launches Xvfb as display :99, starts Fluxbox, and runs x11vnc on port 5900. The X11 session is therefore created and served entirely inside the container. Clients connect via any VNC viewer instead of the host’s X11 socket.
Docker run example
docker run -d -p 5900:5900 \
x11-headless
Connect with a VNC client to localhost:5900. Inside the container you may run xclock or any X11 application; they appear inside the VNC session.
Common Security Note for All Recipes
For production use, replace the broad xhost +local:docker command with a more restrictive grant or mount an Xauthority file generated for the container’s user. The provided run commands assume a Linux host with an active X11 display server. On macOS or Windows, additional configuration (XQuartz or WSLg) is required.