VS Code Running in a Docker Container with X11 Forwarding
I recently wrote a post about running GUI applications in a Docker Desktop container in Linux. This is more challenging than it should be because I use Docker Desktop instead of the Docker Engine. You can read about it here.
The post got the bones of what I wanted in place, but my final goal was to run VS Code in a container and forward the X11 display from the container to the host. Why, you might ask? For a couple of reasons. First, I wanted to see how to do it, and second, to combine with my Claude in a container post so I could add the Claude Code extension to VS Code.
The steps are mostly the same as the previous post (see link above), but I’ve included them for completeness.
The big difference is the Dockerfile, the Microsoft application repository and VS Code are added.
The Dockerfile
Here it is -
FROM ubuntu:24.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y \
x11-apps \
x11-utils \
x11-xserver-utils \
dbus-x11 \
at-spi2-core \
gedit \
fonts-dejavu-core \
fonts-liberation \
adwaita-icon-theme \
gnome-themes-extra \
wget \
curl \
gpg \
sudo \
&& rm -rf /var/lib/apt/lists/*
# Install VS Code from the Microsoft repository
RUN wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > /usr/share/keyrings/microsoft.gpg && \
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list && \
apt-get update && \
apt-get install -y code && \
rm -rf /var/lib/apt/lists/*
# Add a user named bryan, it's better not to run VS Code as root (the password is also bryan)
RUN useradd -m -s /bin/bash bryan && \
echo "bryan:bryan" | chpasswd && \
usermod -aG sudo bryan
USER bryan
WORKDIR /home/bryan
# Alias the code command to add two options
RUN echo "alias code='code --disable-gpu --no-sandbox'" >> /home/bryan/.bashrc
CMD ["/bin/bash"]Build the image with -
docker build -t x11_local_vscode .xhost
In a terminal, run this command -
xhost +local:This allows any local user to connect to the X11 server. This is necessary for the container to be able to connect to the X11 server on the host.
socat
What? socat?
This is the thing that solves the problem that is unique to Docker Desktop. It allows you to forward TCP connections to Linux sockets allowing the X11 display from the container to reach the host.
You probably need to install it. I didn’t have it, and I’ve been using Linux for a long time. On Ubuntu, you can install it with -
sudo apt install socatNow run it with this -
socat TCP-LISTEN:6000,reuseaddr,fork UNIX-CLIENT:/tmp/.X11-unix/X0- TCP-LISTEN:6000 - listen for TCP connections on port 6000, which is the default port for X11.
- reuseaddr - allows the socket to be reused, which is useful if you need to restart the socat command.
- fork - allows multiple connections to be handled simultaneously.
- UNIX-CLIENT:/tmp/.X11-unix/X0 - this is the path to the X11 socket on the host, which is where the X11 server is listening for connections.
Keep this terminal open.
Run the Container
Finally, run the container with this command -
docker run -it --rm \
--add-host=host.docker.internal:host-gateway \
-e DISPLAY=host.docker.internal:0 \
--ipc=host \
--name x11_local_vscode \
x11_local_vscode--add-host=host.docker.internal:host-gateway- adds a host entry forhost.docker.internal, which is the hostname that Docker Desktop uses to refer to the host machine. This is necessary for the container to be able to connect to the X11 server on the host.-e DISPLAY=host.docker.internal:0- sets theDISPLAYenvironment variable in the container to point to the X11 server on the host. The:0part is the display number, which is usually 0 for the first display.--ipc=host- allows the container to share the IPC namespace with the host, some GTK/GL apps require this.--name x11_local_vscode- this is the container name.x11_local_vscode- the name of the image to run.
Running VS Code
Here it is, after all the work.
In the container, run code ., but remember, this is an alias of code --disable-gpu --no-sandbox. It will start and send the display to your host.
Conclusion
Once I figured out how to forward xeyes, adding VS Code wasn’t too difficult, but there were still some challenges. I hope this helps you.
