I have a MultiContainer application where both containers need to display windows.
Container 1 [electron-app] starts with startx /usr/app/reflx-os :0
Container 2 [python-server] starts with python3 /usr/app/server.py and needs to display an OpenCV window.
[electron-app] displays properly. However, when [python-server] tries to open the OpenCV window it throws this error: Gtk: cannot open display: 0
The issue is that the X server is running on the [electron-app]. So how can I get my [python-server] to use the X server from the other container?
It seems like sharing the hosts X server via unix socket is simple:
I attempted some binding workarounds without success.
Attempt 1: I tried creating a shared named volume x-unix:/tmp/.X11-unix
Attempt 2: in my [electron-app] Dockerfile I ran mount --bind /tmp/.X11-unix /data/.X11-unix and in my [python-server] Dockerfile I ran mount --bind /data/.X11-unix /tmp/.X11-unix
In both cases, the X0 socket DOES show up in the [python-server] in /tmp/.X11-unix/X0 but does not seem to function as expected. I tried setting DISPLAY to everything from :0 to :0.0 to unix:0 to localhost:0 to 127.0.0.1:0, etc.
Hi, it could be a permission issue indeed if the container can see the resource but canât make use of it.
What do you mean with âdoes not seem to function as expectedâ? Do you see any error(s) in the logs? What is the expected behaviour and how does it behave instead?
Is it possible to have a look at the Dockerfile.templates and docker-compose.yml of your application?
What I meant by âdoes not seem to function as expectedâ I mean it I get the same Gtk cannot open display: error no matter what.
The only X related log file I can find on [electron-app] is /var/log/Xorg.2.log which unfortunately has nothing even relevant to displays or display errors in it. I cannot find any X related log files on the [python-server]
Thanks for the resources as well, weâll check it out and reach back to you.
In the meantime you could have a look at our x11-window-manager project to check if thereâs something different you can fiddle with
It seems the containers configs are mostly correct, but youâll need to also add UDEV=1 (I think to both containers, but might be wrong) to be able to use the unix socket.
Tell us how it goes after adding it!
Seperate note: Binding the x-unix:/tmp/.X11-unix:rw volume persists the socket files (X0, X1, etc) across pushes of new builds. Each time the container starts X adds/increments a new display. Eventually /tmp/.X11-unix is filled with X0, X1, X2, X3⌠etc.
Itâs not really a problem - just an annoyance. I added rm -r /tmp/.X11-unix to my start.sh file to manually remove defunct sockets.
Hi, Iâve looked through this thread and its not entirely clear to me what the intended result is, do you want your application to display the output of the python-server and electron-app side by side? Or are they displayed on different monitors?
The intent is separate (but overlaying) windows on a single display. The electron-app is a web interface for controlling camera settings. The python-server is an OpenCV window that displays the live camera preview. The intent is for the camera preview to be laying over the center of the web interface.
If I run the python server in the background of the [electron-app] the effect works as intended - but I wanted to containerize the [python-server] for the benefits of supervising, improved logging and code separation.
Update: disabling access control on the main X process using the -ac flag allows the window to show up properly.
From the X manpage:
-ac disables host-based access control mechanisms. Enables access by any host, and permits any host to modify the access control list. Use with extreme caution. This option exists primarily for running test suites remotely.
Unfortunately it doesnât look like THE solution. Though at least weâve narrowed it down to an access/permissions issue.
Hi jassky, if it is working with â-acâ but not without then it seems like a permissions issue. You can use the xhost command to inspect/update the access controls. I think you would want to do something like xhost +python-server from the electron-app container, but you might have to specific the python-server IP.
As another idea here⌠How about exposing the opencv output as a stream endpoint to the electron container and having your frontend display that however it likes? That would alleviate the need to expose the X server and cut this dependency between your containers.
@wrboyce I think you would want to do something like xhost +python-server from the electron-app container, but you might have to specific the python-server IP.
Wouldnât the IP address be the same for all containers?
@robertgzr How about exposing the opencv output as a stream endpoint to the electron container and having your frontend display that however it likes?
I like the level of familiarity I would have with presenting a video stream in a web view - however, frame rate and latency performance and image quality are pretty critical. I assume streaming frames from OpenCV right into X would be faster and look better than streaming over a TCP socket or something. Though I havenât tested thoroughly. If you happen to know of any good solutions for that Iâm all ears.
Wouldnât the IP address be the same for all containers?
Docker has an internal network it uses, on which each container has its own (unique) IP address. In reality, you would probably be okay to whitelist 172.16.0.0/20.
I like the level of familiarity I would have with presenting a video stream in a web view - however, frame rate and latency performance and image quality are pretty critical. I assume streaming frames from OpenCV right into X would be faster and look better than streaming over a TCP socket or something. Though I havenât tested thoroughly.
If you happen to know of any good solutions for that Iâm all ears.
Iâm not really an expert on this⌠but looking around a bit looks like this is not uncharted territory and opencv > gstreamer would be the way to go: