Running ROS with GUI in Docker using Windows Subsystem for Linux 2 (WSL2)

With Virtual RobotX utilizing Docker, it seems like a good time to investigate how Docker can be utilized in improving onboarding. Windows is a very popular OS, and Linux dual booting can be a barrier to entry. Over several days, I researched how to get ROS and Gazebo functional on Docker on a Windows machine thanks to the magic of WSL2. 

I heavily relied on this tutorial by Jack Kawell. It is a great primary guide, but I have a few tips on this post that may help smooth over the experience.

Know that your mileage will vary based on your processing power and RAM. Also obligatory suggestion to always be cautious and make back-ups of important data.

The most important software

You need WSL 2. This requires an update to Windows 10 version 2004. Instructions for this can be found here.

You need to install Docker. With WSL 2, Docker is now available for Windows Home. Yay! Follow the instructions here.

You need to download an X11 server to display the GUI for your Linux apps. I downloaded VcXsrv.

Optional but recommended software

You can download an Ubuntu distro from the Windows store and turn on integration with Docker. I prefer bash to powershell when working with Docker as of right now. Docker describes it as best practice to work fully within WSL when working with Docker for the sake of file access efficiency.

Download Visual Studio Code (VS Code). It has integration with WSL and Docker, allowing you to edit things with a GUI inside WSL from a Windows application. You’ll have to open VS Code and install the plugins for WSL and Docker manually.

Download Windows Terminal from the Windows store. It’s quite handy. Powershell, CMD, and Ubuntu Bash all in one window.

Download and run your Docker container

Open a terminal in either Powershell or Ubuntu and pull your ROS docker image. For the osrf ROS Kinetic image (I have tested this with Melodic as well) use:

docker pull osrf/ros:kinetic-desktop-full

Next you want to run your docker image (osrf/ros:kinetic-desktop-full) interactively (-it) and give it a name (–name ros-test). You also want to set two environmental variables (-e) which are important for connecting to your X11 server. You also want it to run bash.

docker run -it --name ros-test -e DISPLAY=host.docker.internal:0.0 -e LIBGL_ALWAYS_INDIRECT=0 
osrf/ros:kinetic-desktop-full bash

This is what allows the application to find the X server. It needs to connect to an IP designating your vEthernet network adapter for WSL. You wouldn’t believe how long it took me to figure out that all I needed to retrieve that IP was host.docker.internal (when using Docker, of course). Many tutorials for WSL2 rely on the resolv.conf file, but in Docker, it will contain a special IP designating your container instead of your host, so that file only works on a regular distro on WSL2.


This designates how your application will be rendered. If indirect were on, you would need to turn on Native OpenGL in the next step. Unfortunately, some ROS applications will not function with indirect rendering, meaning no native acceleration with WSL.

You should now be in your Docker container.

Now, you’ll need to do the classic ROS commands for making bashrc source your ROS setup.

echo "source /opt/ros/kinetic/setup.bash" >> ~/.bashrc
source ~/.bashrc

And, the moment of truth, start up ROS:


If this works, congratulations, ROS is at least functional.

Configure your X11 server (VcXsrv)

To run VcXsrv, you will open the application, and click through a few settings. Most can stay at default, but ensure that:

  • Native opengl is left unchecked
  • Disable access control is checked

That second option may be concerning to the security-minded. Note that a firewall warning will pop up when first running VcXsrv, giving you the option to disallow communication over private and public networks. I did not allow communication over either. I believe that this means that this should keep VcXsrv secure against external threats, hence why I am comfortable with disabling access control.

Thanks to what I can only describe as the magic of Docker networking, GUI applications from a Docker container will work without disabling any part of the firewall.

However, if you want to run GUI applications from Ubuntu on WSL, then you will want to disable the firewall in such a way to allow private/public networks while listening only to the ports assigned to WSL.

Launching ROS applications

Now, in a new tab/terminal, you want to execute an interactive bash shell in your running container:

docker exec -it ros-test bash

In this new terminal, try running:


If you get some error messages, try googling them, mine were fairly simple to resolve.

Next, try running:

gazebo worlds/

With some luck, Gazebo will now be open, though it may be rather choppy due to the lack of hardware acceleration.

Some other things

I have not tested this enough to know the usefulness or practicality of this, especially Gazebo. I’m also totally new at really using these programs.

I relied heavily on these tutorials and guides:


Microsoft is already beta testing new WSL features, which include a native application for interacting with Linux GUI apps and support for GPU acceleration such as utilizing CUDA. This can be tested now with a Windows Insider build. I might try it later if I’m feeling brave.

Gazebo’s 3D interface is a bit choppy, likely due to the lack of hardware acceleration. I tried using GZweb using an existing Docker container from DukeRobotics. GZweb uses WebGL, allowing rendering to happen client-side from what I can tell. Unfortunately, though the 3D UI felt much more responsive, it was very limited in functionality. Some tweaking might improve this if we try it for ourselves.

Next I want to look into JupyterLab for ROS.

Tags:, ,