DEV Community

Run GUI app in linux docker container on windows host

Robin Kretzschmar on May 22, 2018

What is this about? Docker has dozents of advantages and so is one of them to be able to use apps with a GUI isolated in a docker contai...
Collapse
 
pbrady32 profile image
pbrady32

Hi Robin,

Thanks for the tutorial. When I run docker run -ti --rm -e DISPLAY=$DISPLAY firefox I get the following error. I have set my $DISPLAY variable equal to 10.17.12.01:0.0 (note this is a fake IP I just made up, I'm using my actual IP in the script). Here's the error.

error: XDG_RUNTIME_DIR not set in the environment.
Error: cannot open display: $DISPLAY

Any thoughts?

Collapse
 
pbrady32 profile image
pbrady32

Got it! I was running everything in CMD instead of PowerShell. That was dumb.

Collapse
 
darksmile92 profile image
Robin Kretzschmar

Glad you figured it out by yourself, my first idea would have been to ask if you're using powershell or cmd :)

Thread Thread
 
rots profile image
Rauno Ots

I get the above error also through PowerShell

Thread Thread
 
darksmile92 profile image
Robin Kretzschmar

Rauno, did you try running your PowerShell in elevated mode?

Thread Thread
 
rots profile image
Rauno Ots

Yes, I tried both. I suspect my issue has something to do with Windows Firewall (and corporate antivirus software which has taken control of that).

Thread Thread
 
funskill profile image
funSkill • Edited

Hi Rauno,
Did you fix this issues?
I had the same issue and I solve it just adding the :0.0 after my IP

Thread Thread
 
darksmile92 profile image
Robin Kretzschmar

funSkill, could this comment solve it?

I notice that windows firewall can block the connection to the container.

You can allow this access via firewall settings for "VcXsrv windows xserver".

Also, if you only want to give your xserver private network access, you can use:

Set-NetConnectionProfile -interfacealias "vEthernet (DockerNAT)" -NetworkCategory Private

src

Thread Thread
 
funskill profile image
funSkill • Edited

Hi Robin,
I tried it to but issue solved after adding the :0.0 after my IP

Thanks for article. It' very helpful for me!

Thread Thread
 
darksmile92 profile image
Robin Kretzschmar

Good you figured it out, you're welcome :)

Collapse
 
pbrady32 profile image
pbrady32

Got it! I was running in CMD shell vs Powershell. That fixed the issue.

Collapse
 
chris2048 profile image
Chris2048 • Edited

I'm finding it difficult to auto-insert the DockerNAT IP inside the container, but this seems to work:

--add-host=dockerhost:$((Get-NetIPAddress -AddressFamily IPv4 -InterfaceA
lias "vEthernet (DockerNAT)" | Select IPAddress).IPAddress;) -e DISPLAY=dockerhost:0.0
Enter fullscreen mode Exit fullscreen mode

or

--add-host=dockerhost:$(Get-NetIPAddress -AddressFamily IPv4 -InterfaceAl
ias "vEthernet (DockerNAT)" | Select-Object -ExpandProperty 'IPAddress';) -e DISPLAY=dockerhost:0.0
Enter fullscreen mode Exit fullscreen mode

EDIT: this works too:

DISPLAY=host.docker.internal:0.0
Enter fullscreen mode Exit fullscreen mode
Collapse
 
juandambra profile image
Juan D'Ambra

Hi Robin,

Thanks for the tutorial!

I managed to get Evolution up & running but I'm facing a problem related to gnome-keyring-daemon, which prevents me from storing my credentials and, in turn, login into my account. In Evolution I get the following error:

"Error calling StartServiceByName for org.freedesktop.secrets: GDBus.Error:org.freedesktop.DBus.Error.Spawn.ExecFailed: Failed to execute program org.freedesktop.secrets: Operation not permitted"

If I open a terminal into the container and try to execute the daemon by hand I get:

root@96c2c004a2cb:~# gnome-keyring-daemon
bash: /usr/bin/gnome-keyring-daemon: Operation not permitted
root@96c2c004a2cb:~# echo $?
126

Any ideas?

Collapse
 
darksmile92 profile image
Robin Kretzschmar • Edited

Hi Juan,

from what I know gnome-keyring needs an active GDM session - which we don't have in this case.

Please try to attach these lines to /etc/pam.d/login:


auth optional pam_gnome_keyring.so
session optional pam_gnome_keyring.so auto_start

The daemon needs to be running. Either use --daemonize or run the following command:


gnome-keyring-daemon --login

Maybe you need your password (of the ubuntu user):


echo -n "somewildpasswrd" | gnome-keyring-daemon --login

I did not test it because I switched my work notebook also to linux but please try this and let me know :)

Collapse
 
juandambra profile image
Juan D'Ambra

Hi Robin,

Thank you for your answer.

I tried the steps you suggested, but to no avail. I added the following lines to the Dockerfile:

RUN echo "auth optional pam_gnome_keyring.so" >> /etc/pam.d/login
RUN echo "session optional pam_gnome_keyring.so auto_start" >> /etc/pam.d/login

But it did not make any difference. I also tried to execute gnome-keyring-daemon with the options you mentioned, but it keeps failing with "Operation not permitted" and exit code 126:

root@bd0d9115600d:/# gnome-keyring-daemon --login
bash: /usr/bin/gnome-keyring-daemon: Operation not permitted
root@bd0d9115600d:/# gnome-keyring-daemon --daemonize
bash: /usr/bin/gnome-keyring-daemon: Operation not permitted
root@bd0d9115600d:/# echo -n "notmypassword" | gnome-keyring-daemon --login
bash: /usr/bin/gnome-keyring-daemon: Operation not permitted

I even found the command D-Bus uses to start the daemon and tried to use it on my own, but again no luck:

root@bd0d9115600d:/# cat /usr/share/dbus-1/services/org.freedesktop.secrets.service
[D-BUS Service]
Name=org.freedesktop.secrets
Exec=/usr/bin/gnome-keyring-daemon --start --foreground --components=secrets
root@bd0d9115600d:/# /usr/bin/gnome-keyring-daemon --start --foreground --components=secrets
bash: /usr/bin/gnome-keyring-daemon: Operation not permitted

I ended up firing up a Vagrant box over VirtualBox to get this working, since my goal was not to use it on a daily basis, but merely makin a PoC of using Evolution and the evolution-ews plugin with Outlook in Office 365 with MFA enabled (something you cannot do in Thunderbird, for example). My PoC was successful, BTW! :)

Sad this didn't work out, it was neater using Docker :(

Thank you for your help!

Thread Thread
 
darksmile92 profile image
Robin Kretzschmar

Hi Juan,

you're welcome! Good to see your POC worked out! :)
I took an hour to do some research on this and it seems like more people are encountering this limitation. Even Docker is not intended to do such things, it would be really nice to use it.

I agree with you that vagrant is a way but Docker would be much nice to use :)

Collapse
 
barrenaedu profile image
Eduardo Barrena

Here it is the solution > unix.stackexchange.com/questions/4...

Collapse
 
chris2048 profile image
Chris2048

I notice that windows firewall can block the connection to the container.

You can allow this access via firewall settings for "VcXsrv windows xserver".

Also, if you only want to give your xserver private network access, you can use:

Set-NetConnectionProfile -interfacealias "vEthernet (DockerNAT)" -NetworkCategory Private

src

Collapse
 
darksmile92 profile image
Robin Kretzschmar

Hey Chris thanks for making me aware of this!
The PowerShell command can come in handy, thanks 😊

Collapse
 
arievdb profile image
Arie van den Bos • Edited

Hi Robin,

Thanks for the nice explanation. I was wondering if you or any other reader has ever tried running this on a windowsservercore container on Docker for Windows?

On Ubuntu I got it working the way you described. For certain reasons I am now trying to run Firefox on windowsservercore but without succes.

Thanks,

Arie

Collapse
 
darksmile92 profile image
Robin Kretzschmar

Hi Arie,

as of my understanding windows server core it not capable of running such GUI applications by default. I researched that and came across this article on medium which has some information on how to add GUI capabilities to windows server core.

But I think more of interest for you would be this youtube video where they try Chrome, Firefox and Opera on Windows Server Core. (v.1709)

Result of video:

  • Google Chrome: Working
  • Opera: Working
  • Mozilla Firefox: Not working

Collapse
 
apollo2030 profile image
Alexandru Dobinda • Edited

Hi Robin,

Thanks for this tutorial! I was missing the ip address part - now it works!
I needed this in order to use the android studio docker container on a windows machine.

Thanks again!
Alexandru

Collapse
 
darksmile92 profile image
Robin Kretzschmar • Edited

Great to hear it helped you, Alexandru :)

Collapse
 
oaparfene profile image
oaparfene

Hi Robin,

when running: docker run -ti --rm -e DISPLAY=$DISPLAY firefox i get the following error. I am using admin powershell and i set DISPLAY to my IP.

Unable to find image 'firefox:latest' locally
docker: Error response from daemon: pull access denied for firefox, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.

I ran docker login successfully but that didnt change anything. I'm trying to get a vncserver with xterm working in a docker container but im very new to all of this. I wanted to test your code to see if i can get a GUI up and running.

Help would be much appreciated!

Collapse
 
darksmile92 profile image
Robin Kretzschmar

Hi oaparfene,

can you please post the content of your Dockerfile?
Also, it is important which name you gave your build.

So you should have the Dockerfile in a folder and then run a PowerShell instance (as admin), change into the directory where your Dockerfile is and run the docker build -t firefox . command first. The firefox at the end is the name the image will be labeled with after the build and this name should be used in the docker run command.

Collapse
 
oaparfene profile image
oaparfene

Hi Robin,

thank you for the reply. Turns out the mistake i made was naming my Dockerfile "firefox" instead of "Dockerfile"

Collapse
 
filips profile image
Filip Š

Is it possible to do this with Docker Toolbox with VirtualBox?

What should be changed?

Collapse
 
darksmile92 profile image
Robin Kretzschmar

This should also be possible with Docker Toolbox.
I can't test it with VirtualBox at the moment. But I can imagine that there could be some issues regarding administrative rights, so maybe you need to run everything elevated to get it working.

Collapse
 
filips profile image
Filip Š • Edited

I will try to test this myself this week.

I have concerns about connecting graphics in VirtualBox with the host system.
Docker Toolbox uses seperate virtual system (based on Linux) so maybe graphics will be forwarded only to it not to Windows.

But if graphics can be forwarded directly to Windows, it will probably work.

I will post the solution when I find it.

Thread Thread
 
darksmile92 profile image
Robin Kretzschmar • Edited

You're right, this could be a problem with forwarding stopping at the virtual system.
I am curious what your results will be!

Thread Thread
 
filips profile image
Filip Š • Edited

I tested this and it works!

Display variable should be set to address of host (Windows) computer.

When using boot2docker image, new VirtualBox Host-Only Network will be created. In it, host computer will probably have address 192.168.99.1, so DISPLAY should be set to 192.168.99.1:0.0

If that won't work, new bridged network can be added to boot2docker image and DISPLAY should be set to local address of host.

Also, because boot2docker image has very low RAM and GPU memory, GUI apps will often crash. This could probably be fixed with higher RAM and GPU memory settings in VirtualBox.

Collapse
 
raquelro profile image
Raquel Rodriguez

Hi Robin!
Thank you for your article but I still have the problem
error: XDG_RUNTIME_DIR not set in the environment.
I have done all you discussed but I cannot make it work, any suggestion?
Thank you

Collapse
 
darksmile92 profile image
Robin Kretzschmar • Edited

Hey Raquel,

normally this would be set by your WM but sometimes - especially under wsl - sometimes this is not the case.
Try adding the following to your ~/.bashrc file (applies for your current wsl user):

export DISPLAY=:1 #optional
export XDG_RUNTIME_DIR=/home/USERNAME/tmp
Enter fullscreen mode Exit fullscreen mode

You can choose any folder for XDG_RUNTIME_DIR.

In case you are wondering what the hell XDG_RUNTIME_DIR is...
This is an environment variable that any program will access to determine the user specific directory to store small temporary files to. Normally it is set automatically when you log in.

Collapse
 
raquelro profile image
Raquel Rodriguez

Thanks Robin, I tried it but the error persists....any other ideas? :(

Thread Thread
 
raquelro profile image
Raquel Rodriguez

I found this log .... maybe it can help:
Welcome to the VcXsrv X Server
Vendor: The VcXsrv Project
Release: 1.20.8.1

OS: Windows NT 6.2 build 9200 (64-bit)
Contact: marha@users.sourceforge.net

LoadPreferences: C:\Users\RaquelRodriguez\AppData\Roaming.XWinrc not found
LoadPreferences: Loading C:\Program Files\VcXsrv\system.XWinrc
Warning: Locale not supported by X, falling back to 'C' locale.
(II) AIGLX: Testing pixelFormatIndex 1
(II) GLX: enabled GLX_SGI_make_current_read
(II) GLX: enabled GLX_SGI_swap_control
(II) GLX: enabled GLX_MESA_swap_control
(II) GLX: enabled GLX_SGIX_pbuffer
(II) GLX: enabled GLX_ARB_multisample
(II) GLX: enabled GLX_SGIS_multisample
(II) GLX: enabled GLX_ARB_fbconfig_float
(II) GLX: enabled GLX_EXT_fbconfig_packed_float
(II) GLX: enabled GLX_ARB_create_context
(II) GLX: enabled GLX_ARB_create_context_profile
(II) GLX: enabled GLX_ARB_create_context_robustness
(II) GLX: enabled GLX_EXT_create_context_es2_profile
(II) GLX: enabled GLX_ARB_framebuffer_sRGB
(II) AIGLX: enabled GLX_MESA_copy_sub_buffer
(II) 105 pixel formats reported by wglGetPixelFormatAttribivARB
(II) GLX: Initialized Win32 native WGL GL provider for screen 0
winClipboardThreadProc - DISPLAY=127.0.0.1:0.0
Using Composite redirection
OS maintains clipboard viewer chain: yes
winMultiWindowXMsgProc - Fatal error 1 on xcb connection
winClipboardIOErrorHandler!
winClipboardProc - setjmp returned for IO Error Handler.
(II) Server terminated successfully (0). Closing log file.

Thread Thread
 
raquelro profile image
Raquel Rodriguez

Hi Robin!
Finally I made it work :)
I'm not sure what was the problem, I just decided to remove the docker image and container, install it again and ...... worked!
Thank you very much :)

Thread Thread
 
darksmile92 profile image
Robin Kretzschmar

Great news! Sometimes it's the best solution to just start over. Glad you got it working 👍😊

Collapse
 
santoshburada profile image
santosh-burada

Hi,Robin

I'm want to access the webcam **but I cant
**This is docker run command

docker run --privileged --rm -it -e DISPLAY=192.168.56.1:0.0 --device=/dev/video0:/dev/video0 -v /tmp/.X11-unix:/tmp/.X11-unix face2_mysql

This is the error I got

VIDEOIO ERROR: V4L: can't find camera device
VIDEOIO ERROR: V4L: can't find camera device
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/local/lib/python3.7/tkinter/init.py", line 1705, in call
return self.func(*args)
File "/usr/app/Facerec.py", line 105, in FaceRecognition
fraud=self.ObjectDetectionP2(img,c)
File "/usr/app/Facerec.py", line 48, in ObjectDetectionP2
blob = cv2.dnn.blobFromImage(img, 1 / 255, (WidthHeightTarget, WidthHeightTarget), [0, 0, 0], 1, crop=False)
cv2.error: OpenCV(3.4.2) /opt/opencv-3.4.2/modules/imgproc/src/resize.cpp:4044: error: (-215:Assertion failed) !ssize.empty() in function 'resize'

Collapse
 
entrptaher profile image
Md Abu Taher • Edited

Ultimately this requires a GUI on my host, so where the memory and CPU are gonna be used? By the docker or by my host?

Can this be hacked to run on EC2 or Lambda? :D

Collapse
 
ikirker profile image
Ian Kirker

You won't be able to mount your local machine's filesystems remotely (unless you set that up separately), but the whole point of the X system is to be able to run GUI applications remotely while passing their interface back to your local machine.

Once you have an X server running (as explained in this article), if you use SSH, your SSH client should be able to handle passing back the interface automatically. (Usually referred to as X-Forwarding.)

Otherwise you'll have to tinker with firewalls and manually configuring the network connection, and it's somewhat less secure.

Collapse
 
darksmile92 profile image
Robin Kretzschmar

The Ressources of your docker container will be used. You can see that with the command docker top CONTAINER.
Interesting question, I haven't worked with Amazon Lambda until now but from what I've read about it, my understanding was Lambda can only take pure functions and run them.
It would be interesting if EC2 instances can run docker virtualizations in them.

Maybe you want to try and make a post about it? :)

Collapse
 
zeerorg profile image
Rishabh Gupta • Edited

You can run dockerized x server apps on ec2 but there are two ways you can get gui.

  1. Forwarding X using ssh, this will be very slow as X11 requires very high bandwidth and very low latency to work with reasonable speed.
  2. Using VNC, this can be done but I personally haven't tried it
Collapse
 
drachehavoc profile image
Daniel de Andrade Varela

It works here, but Firefox runs too slow...

I think firefox runs slow because X11 is connected via ethernet, is there a way to connect directly to the host?

Collapse
 
darksmile92 profile image
Robin Kretzschmar

It ran smoothly on my setup (Latest Windows 10 + Docker CE).
Which Powershell Version are you using? I used v1 because this worked out the best to my experience.

I don't know about a way to connect directly.
What comes to my mind as alternative is to use a VNC solution (installing xfce and tightvnc) and then connect.

Maybe there are better X11 solutions for windows with better performance that I don't know about :)

Collapse
 
xiaodaigh profile image
evalparse

"Find out your ip address with" it's very clear what's the ip address I am looking for.

Collapse
 
erenseymen profile image
Eren Seymen

I've dockerized Asbru Connection Manager. It's a Linux-only application that I use to manage my ssh connections. I like asbru more than its Windows counterpart mremoteNG.

Collapse
 
mjkrause profile image
Michael Krause

Hi Robin,

Awesome post! I'm not getting any audio (e.g., on YouTube). I suppose X11 only serves video? Do you have any ideas how to get audio signals?

Thanks

Collapse
 
darksmile92 profile image
Robin Kretzschmar

Hi Michael,

I never had a use case to play audio via WSL. But in theory it should work when you install PulseAudio on both WSL and Windows host. I just checked, for Windows there is a download with binaries and setup. Inside your distro in WSL it should be simple to install with the package manager.

I did a quick research and found this article that seemed like a good tutorial (scroll down to the "Enabling Audio" section).

If you struggle at some point with that, comment here and I'll try to help :)

Collapse
 
drachehavoc profile image
Daniel de Andrade Varela

I got the same error even running in Powershell or Docker Terminal, I'm using Docker Toolbox...

Collapse
 
gfijrb profile image
Paul Bolharskih

set-variable command is in window env not found!

Collapse
 
darksmile92 profile image
Robin Kretzschmar

Paul, are you using Powershell? Set-Variable is not available in cmd, you need to use Powershell for that.

Collapse
 
ganesshkumar profile image
Ganessh Kumar

Is there any way to do similar thing with audio?

Collapse
 
darksmile92 profile image
Robin Kretzschmar

I once saw a run command with the parameter --device /dev/snd to enable the sound. But I don't know if it will be passed on to the host.

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
swcarden profile image
swcarden

I also had this problem. I re-ran Xlaunch configuration and checked "No access control", and then it worked.