Building a dockerized GUI by sharing the host screen with docker container
Few months ago, I decided to build my own smart mirror using a Raspberry Pi 4 (I will share that experience later). But I wanted to build the software I wanted to use for the smart mirror before ordering my raspberry pi.
My technology choice went to Python3, using the TK library for python to build the GUI. I also wanted to dockerize the application for easier development. But problem: TK requires a display to work, and the python docker container I am using does only have a command line interface.
After few research and trying different solutions, I manage to have a definitive solution.
Procedure to share a display with a docker container on macOS Catalina
Using a MacBook Pro and macOS Catalina, here is what I found:
- Download Xquartz (https://www.xquartz.org) & install it
When installed, run the software and make sure to select in the
xQuartz > preferences > Security
the option “Allow connections from network” should be checked.
- Allow your screen to be shared with local environment running on your laptop
By simply typing in a terminal: `xhost +127.0.0.1`. The output “127.0.0.1 being added to access control list” should be displayed if everything went well. That command has to be run every time you stop the application xQuartz on your laptop.
- Share the screen with your docker container running
It is where it is a bit tricky. Here is how you have to run your docker container in order to share the laptop screen to the application running in docker:
docker run -i -t - rm -e DISPLAY=host.docker.internal:0 -v /tmp/.X11-unix:/tmp/.X11-unix:ro - name="my_container_name" namespace/container
-e DISPLAY => we create an environmental variable named DISPLAY in the container and value will be the host machine IP (your laptop, on Mac it should always be host.docker.internal) and the number identifying the screen (if you don’t have 2 screens, it should be 0. If you are having multiple screens, you will have to figure out the number of the screen.
-v /tmp/.X11-unix:/tmp/.X11-unix:ro => sharing the X11 information about the screen in read-only mode.
And that’s it, the rest is pretty similar to what we use on a normal docker environment. The docker container will be killed as soon as the application stops running. In my case with python TK, as soon as I close the GUI, the docker-container stops and get removed.
I am always impressed by what we can do with docker. It is indeed very useful for backend development, but it can be used in different context, and using that trick, you can actually run softwares inside a docker container instead of actually installing anything on your laptop.
The downside is actually it is not straightforward to share a display, it is actually not necessarily advised to allow display to be shared with third party software and would also only do that in development mode. In the actual running system, just run the program using the python3 command line on the system itself.