Can you run GUI applications in a Linux Docker container?
Solution 1
You can simply install a vncserver along with Firefox :)
I pushed an image, vnc/firefox, here: docker pull creack/firefox-vnc
The image has been made with this Dockerfile:
# Firefox over VNC
#
# VERSION 0.1
# DOCKER-VERSION 0.2
FROM ubuntu:12.04
# Make sure the package repository is up to date
RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
RUN apt-get update
# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way to do it, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'
This will create a Docker container running VNC with the password 1234
:
For Docker version 18 or newer:
docker run -p 5900:5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
For Docker version 1.3 or newer:
docker run -p 5900 -e HOME=/ creack/firefox-vnc x11vnc -forever -usepw -create
For Docker before version 1.3:
docker run -p 5900 creack/firefox-vnc x11vnc -forever -usepw -create
Solution 2
Xauthority becomes an issue with newer systems. I can either discard any protection with xhost + before running my docker containers, or I can pass in a well prepared Xauthority file. Typical Xauthority files are hostname specific. With docker, each container can have a different host name (set with docker run -h), but even setting the hostname of the container identical to the host system did not help in my case. xeyes (I like this example) simply would ignore the magic cookie and pass no credentials to the server. Hence we get an error message 'No protocol specified Cannot open display'
The Xauthority file can be written in a way so that the hostname does not matter. We need to set the Authentication Family to 'FamilyWild'. I am not sure, if xauth has a proper command line for this, so here is an example that combines xauth and sed to do that. We need to change the first 16 bits of the nlist output. The value of FamilyWild is 65535 or 0xffff.
docker build -t xeyes - << __EOF__
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
__EOF__
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth
xauth nlist :0 | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run -ti -v $XSOCK:$XSOCK -v $XAUTH:$XAUTH -e XAUTHORITY=$XAUTH xeyes
Solution 3
I just found this blog entry and want to share it here with you because I think it is the best way to do it and it is so easy.
http://fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker/
PROS:
+ no x server stuff in the docker container
+ no vnc client/server needed
+ no ssh with x forwarding
+ much smaller docker containers
CONS:
- using x on the host (not meant for secure-sandboxing)
in case the link will fail someday I have put the most important part here:
dockerfile:
FROM ubuntu:14.04
RUN apt-get update && apt-get install -y firefox
# Replace 1000 with your user / group id
RUN export uid=1000 gid=1000 && \
mkdir -p /home/developer && \
echo "developer:x:${uid}:${gid}:Developer,,,:/home/developer:/bin/bash" >> /etc/passwd && \
echo "developer:x:${uid}:" >> /etc/group && \
echo "developer ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/developer && \
chmod 0440 /etc/sudoers.d/developer && \
chown ${uid}:${gid} -R /home/developer
USER developer
ENV HOME /home/developer
CMD /usr/bin/firefox
build the image:
docker build -t firefox .
and the run command:
docker run -ti --rm \
-e DISPLAY=$DISPLAY \
-v /tmp/.X11-unix:/tmp/.X11-unix \
firefox
of course you can also do this in the run command with sh -c "echo script-here"
HINT: for audio take a look at: https://stackoverflow.com/a/28985715/2835523
Solution 4
With docker data volumes it's very easy to expose xorg's unix domain socket inside the container.
For example, with a Dockerfile like this:
FROM debian
RUN apt-get update
RUN apt-get install -qqy x11-apps
ENV DISPLAY :0
CMD xeyes
You could do the following:
$ docker build -t xeyes - < Dockerfile
$ XSOCK=/tmp/.X11-unix/X0
$ docker run -v $XSOCK:$XSOCK xeyes
This of course is essentially the same as X-forwarding. It grants the container full access to the xserver on the host, so it's only recommended if you trust what's inside.
Note: If you are concerned about security, a better solution would be to confine the app with mandatory- or role-based-access control. Docker achieves pretty good isolation, but it was designed with a different purpose in mind. Use AppArmor, SELinux, or GrSecurity, which were designed to address your concern.
Solution 5
OSX
Jürgen Weigert has the best answer that worked for me on Ubuntu, however on OSX, docker runs inside of VirtualBox and so the solution doesn't work without some more work.
I've got it working with these additional ingredients:
- Xquartz (OSX no longer ships with X11 server)
- socket forwarding with socat (brew install socat)
- bash script to launch the container
I'd appreciate user comments to improve this answer for OSX, I'm not sure if socket forwarding for X is secure, but my intended use is for running the docker container locally only.
Also, the script is a bit fragile in that it's not easy to get the IP address of the machine since it's on our local wireless so it's always some random IP.
The BASH script I use to launch the container:
#!/usr/bin/env bash
CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
NIC=en0
# Grab the ip address of this box
IPADDR=$(ifconfig $NIC | grep "inet " | awk '{print $2}')
DISP_NUM=$(jot -r 1 100 200) # random display number between 100 and 200
PORT_NUM=$((6000 + DISP_NUM)) # so multiple instances of the container won't interfer with eachother
socat TCP-LISTEN:${PORT_NUM},reuseaddr,fork UNIX-CLIENT:\"$DISPLAY\" 2>&1 > /dev/null &
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth.$USER.$$
touch $XAUTH
xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f $XAUTH nmerge -
docker run \
-it \
--rm \
--user=$USER \
--workdir="/Users/$USER" \
-v "/Users/$USER:/home/$USER:rw" \
-v $XSOCK:$XSOCK:rw \
-v $XAUTH:$XAUTH:rw \
-e DISPLAY=$IPADDR:$DISP_NUM \
-e XAUTHORITY=$XAUTH \
$CONTAINER \
$COMMAND
rm -f $XAUTH
kill %1 # kill the socat job launched above
I'm able to get xeyes and matplotlib working with this approach.
Windows 7+
It's a bit easier on Windows 7+ with MobaXterm:
- Install MobaXterm for windows
- Start MobaXterm
- Configure X server: Settings -> X11 (tab) -> set X11 Remote Access to full
- Use this BASH script to launch the container
run_docker.bash
:
#!/usr/bin/env bash
CONTAINER=py3:2016-03-23-rc3
COMMAND=/bin/bash
DISPLAY="$(hostname):0"
USER=$(whoami)
docker run \
-it \
--rm \
--user=$USER \
--workdir="/home/$USER" \
-v "/c/Users/$USER:/home/$USER:rw" \
-e DISPLAY \
$CONTAINER \
$COMMAND
Will
Updated on September 09, 2021Comments
-
Will over 2 years
How can you run GUI applications in a Linux Docker container?
Are there any images that set up
vncserver
or something so that you can - for example - add an extra speedbump sandbox around say Firefox? -
user94154 over 10 yearsHow would I use a VNC client to view this remotely? Typing in the IP + port doesn't seem to be working.
-
creack over 10 yearsFirst, you need to check the port allocated (by doing
docker inspect <container id>
or simplydocker ps
, then you connect to your host's ip with the port you just found. -
timthelion about 10 yearsPlease note that subuser is still very new and relatively untested. If you run into any problems please submit bug reports!
-
Will about 10 yearsI'd avoid X11 if there's any way you can. Your killer app would be running the tor proxy in docker, and running a full browser with plugins in a child docker such that firewalling etc forces all network out via the tor docker. This would run laps around the current tor browser bundle for web usability because you'd let rich content through.
-
timthelion about 10 yearsIs the trouble for you with X11 security? Or is it that you want this working with windows? Or that you want this to work remotely? All of the above? I think that making this work with vnc is quite possible(though I wouldn't make it the default method because it adds a dependency on vnc). Making subuser work remotely isn't really possible/meaningfull. There is also this: github.com/rogaha/docker-desktop but from the bug reports it seems xpra might be unusable in real life.
-
Will almost 10 years(This is great for trusted apps. For any kind of sandboxing, though, you want to avoid X-forwarding.)
-
Bruno Adelé almost 10 yearsYou can see the equivalent 5900 port with this command
docker ps | grep -Po ':\K[0-9]*'
-
Will over 9 yearsThis is great if security isn't a concern. If the purposes of dockering something are to isolate it, its best to avoid X11 in-out of the container.
-
Tully over 9 yearsYou also need to allow access to the X Server from other hosts using a tool like xhost. To completely open it up use
xhost +
on the host. -
Aryeh Leib Taurog over 9 years@Tully only
xhost +local
is necessary. It would be better to make the~/.Xauthority
file available in the container however, so it can authenticate itself. -
Karl Forner over 9 yearshave you managed to get it working on a Mac (using boot2docker) ?
-
Aryeh Leib Taurog over 9 years@KarlForner sorry, I've only got linux here.
-
alfonsodev over 9 yearsthe creackfirefox-vnc image fails with error: Enter VNC password: stty: standard input: Inappropriate ioctl for device fgets: No such file or directory stty: standard input: Inappropriate ioctl for device x11vnc -usepw: could not find a password to use.
-
Cristopher Van Paul over 9 yearsUse docker well > Running GUI apps with Docker fabiorehm.com/blog/2014/09/11/running-gui-apps-with-docker
-
pablo over 9 yearsHow can I find the firefox window id and share only the firefox window? x11vnc has the -id <window> option but I don't know how to find the id. A terminal window is also opened and I'm not sure why.
-
Sudipta Basak over 9 yearsNot clear what is the username and password. Which vnc client to use and how to connect?
-
creack over 9 yearsThere is no username, the password is clearly indicated in the answer and any vnc client will do. In my case, I like the native osx one. (from finder, press command+K and connect to vnc://<docker ip>:<container exposed port>)
-
Manglu almost 9 yearsIs there a way to change the screen resolution. When I used this image it uses only 50% of the real estate.
-
cboettig almost 9 yearsThis was working rather nicely for me on an Ubuntu 14.04 laptop with docker 1.5 earlier; but is now failing for me on Ubuntu 15.04, docker 1.6.2, with the error
Can't open display: :0
. Any ideas? -
cboettig almost 9 yearsI see my problem on 15.04 is solved by the XAuthority mapping listed in Jürgen Weigert's solution below.
-
Fish Monitor almost 9 years@KarlForner, for OS X see kartoza.com/…. This is much easier.
-
creack over 8 yearsI think 12.04 is not supported anymore. If you bump to 14.04 it should work. Might need to update the universe repo as well.
-
Robert Haines over 8 yearsIf you'd rather not mount the whole home directory into the container you can just mount the
.Xauthority
file itself:-v $HOME/.Xauthority:/root/.Xauthority -e XAUTHORITY=/root/.Xauthority
. -
Nick Breen over 8 yearsI used
xhost +si:localuser:$USER
to authorise just the user starting the container. -
Yair Zaslavsky about 8 yearsI found the port the vnc server mapped to, and the docker version I am using is (on ubuntu 14.04) 1.10.2. When I run vncviewer localhost:32776 -passwd ~/.vnc/passwdfile I do not see firefox, but i see Thu Feb 25 07:07:31 2016 CConn: connected to host localhost port 32776 main: End of stream Can anyone help please?
-
Piotr Aleksander Chmielowski about 8 yearsJust a note,
-v $XSOCK:$XSOCK -v $XAUTH:$XAUTH
can be shortened to-v $XSOCK -v $XAUTH
-
valentt almost 8 years@creack awesome works, but please, please, please include run example in Dockerfile and on your github, or at least link to this stackoverflow question.
-
creack almost 8 yearsDone. Didn't test if still working though. hub.docker.com/r/creack/firefox-vnc
-
Peter Butkovic almost 8 yearsfor centos version see: github.com/CentOS/CentOS-Dockerfiles/blob/master/firefox/…
-
tbc0 over 7 years@PiotrAleksanderChmielowski that did not work for me, Docker version 1.12.0, build 8eab29e
-
Aleksandr Dubinsky over 7 yearsI seemed to need
-t
indocker run
to get a password prompt. I'm not sure why a password is even needed in this. Anyway, please update the instructions by editing the original instructions rather than adding "EDIT" sections. -
Piotr Aleksander Chmielowski over 7 years@tbc0 - interesting. Maybe it is a bug to report?
-
TmTron over 7 years@AryehLeibTaurog I think the trailing colon is missing in your command
xhost +local:
. Without the colon, the command failed on Ubuntu 16.04 -
Dirk over 7 yearsDoes not work for me either:
Error: Can't open display: :0
Docker v1.8.2-7 on Fedora 22. -
johndodo over 7 years@Dirk: You might want to replace
:0
with$DISPLAY
. That meansxauth nlist $DISPLAY | ...
anddocker run -ti -e DISPLAY=$DISPLAY ...
. Usually the X DISPLAY is:0
, but not always (and especially not if you are connecting via ssh -X). -
Lisael about 7 yearsI changed this Dockerfile to use
.xinitrc
instead of.bashrc
:RUN echo "exec firefox" > ~/.xinitrc && chmod +x ~/.xinitrc
.x11vnc -create ...
opens a new display and tries to run .xinitrc -
dashesy about 7 yearsTo run a desktop in docker under vnc ConSol has a nice solution.
-
ingomueller.net about 7 yearsInstead of changing
X11UseLocalhost
, you can also use the additional option--net=host
for thedocker run
command (found here). -
deller almost 7 yearsi didnt understand what you meant by the bash script - how do i run it in windows?
-
Nick almost 7 years@deller I do software development on windows using GIT, so I have the GIT-bash shell available to me.
-
mguijarr almost 7 yearsJust for people landing here: @PiotrAleksanderChmielowski comment did not work for me, and I also had to add
--net=host
-
guilhermecgs almost 7 yearshas anyone tested this?
-
dashesy almost 7 years@guilhermecgs yes, and works fine. Since then I also tried
xpra
in docker, which is root-less X.xpra
was the best suited IMO and is more efficient than VNC. -
guilhermecgs almost 7 yearsJust to be clear... Can I have a full desktop experience (GNOME, KDE) with this image?
-
dashesy almost 7 yearsI only tried the Xfce4 and IceWM (which is in that repo). Of course the experience will be limited, for example mounting devices will not show up in the desktop (gvfs) unless you pass
--device /dev/...
to the docker and set necessary--cap
privileges. That defeats the purpose of containment, but you can pass through devices. With some tweaking it should be possible I believe to run GNOME/KDE under VNC. I ran multiple X in docker with nvidia cards (no VNC or Xpra), so that is certainly doable. -
Abai over 6 yearsOn Ubuntu 16.04 xauth creates the
/tmp/.docker.xauth
file with600
permissions. This results in xauth inside docker container not being able to read the file. You can verify by runningxauth list
within the docker container. I have addedchmod 755 $XAUTH
after thexauth nlist :0 | ...
command to resolve this. -
user3275095 over 6 yearsI followed the steps. However, I get
error: XDG_RUNTIME_DIR not set in the environment.
andError: cannot open display: VAIO:0.0
. Did you encounter something like this? -
Daniel Alder about 6 years@Abai Why using 755, if 444 or 644 is enough?
-
toschneck about 6 yearsWe didn't tried it so far. The biggest challenge on this would be to bring up a working D-Bus daemon. Most of the gnome or KDE desktops will need them. May the ubuntu-desktop-lxde-vnc project helps you there.
-
readytotaste almost 6 yearsHow can I do this on windows 7? Do I need to install an X server?
-
A. Binzxxxxxx almost 6 yearsAs most answers here this applies only to unix I think - until windows supports X server window system.
-
readytotaste almost 6 yearsDo you think it could work if I installed X server on windows or even bundled an X server into my Docker container?
-
A. Binzxxxxxx almost 6 yearsinstalling X server into your docker does not make much sense since this is what I try to avoid and you would still need to render it to the display then. One of the vnc answers may fit you in your case.
-
A. Binzxxxxxx almost 6 yearsHowever I could imagine it may work with Xming or Cygwin/X. Please write a comment if you got it working.
-
readytotaste almost 6 yearsOkay will try installing Xming on windows and then try this.. One thing Im confused about is that the docker toolbox for windows runs inside Boot2Docker, which is a stripped down version of Linux for the Docker daemon.. Do you think I could install X server on this and run it with the exact same flags as above?
-
readytotaste almost 6 yearsHow can I make this work on Windows 7? Since, it does not have X server capability?
-
readytotaste almost 6 yearsHas anyone figured out X forwarding for windows?
-
readytotaste almost 6 yearsI get an error pertaining to the user not being found i.e. "no matching entries in passwd file" Any leads?
-
readytotaste almost 6 yearsI was actually able to get it to work using MobaXTerm by using the Dockerfile as above and modifying the docker run command to mount /tmp/.X11-unix to /c:/Users/username and set the host IPv4 address for the DISPLAY environment variable..
-
Alejandro Galera almost 6 yearsI think you also need to install in Dockerfile
apt-get -y install sudo
to create/etc/sudoers.d
folder. -
vladkras almost 6 yearsworks perfect with noVNC client directly in browser. Tested: consol/ubuntu-xfce-vnc
-
CMCDragonkai over 5 yearsI have found that you don't even eed to pass the
/tmp/.X11-unix
socket at all. It just works with mounting.Xauthority
and--net=host
. -
Jan Hudec over 5 years@walksignison, Install X server. There are three options: VcXsrv, Xming and Cygwin/X. xauth acts up a bit for me though; due to lack of unix domain sockets, the DISPLAY ends up being 127.0.0.1:0 and xauth does not accept it in some commands.
-
readytotaste over 5 years@janhudec I was able to get it to work with Moba XTerm! Thanks a lot anyway!
-
Christian Hujer over 5 yearsThis will probably work everywhere. But If the host is Linux with X11, this is overkill. If the host is Linux with X11, X11 based solutions will be more light-weight.
-
Christian Hujer over 5 yearsThis does not work in the latest versions of docker. Docker refuses to mount from volumes where the host has the sticky bit set.
-
Christian Hujer over 5 yearsThis is actually the only solution that works these days. Using
/tmp/.X11-unix
as volume no longer works, as docker silently refuses volume mounts from sticky directories. -
kgibm over 5 yearsThe following worked for me (in particular, adding
-e DISPLAY=$DISPLAY
), replacing the last four lines with:xauth nlist $DISPLAY | sed -e 's/^..../ffff/' | xauth -f /tmp/.docker.xauth nmerge - && docker run -it -v /tmp/.X11-unix:/tmp/.X11-unix -v /tmp/.docker.xauth:/tmp/.docker.xauth -e XAUTHORITY=/tmp/.docker.xauth -e DISPLAY=$DISPLAY xeyes
-
stelios about 5 years@Abai Good point! However you need
chmod
beforexauth nlist ...
-
orodbhen almost 5 yearsI think it depends on what distro you're using. You definitely can bind-mount the X11 Unix socket on CentOS. It's also important to understand what
--network=host
does. It gives your container full access to the host's network stack, which may be undesirable, depending on what you're trying to do. If you're just tinkering with running containerized GUIs on your desktop, then it shouldn't matter. -
user1145922 over 4 yearsThis is the only one that would work for me. For my purposes, I was able to minimize it to this: docker run --network=host --volume=
echo ~
:/home/${USER} --user=id -u ${USER}
--env="DISPLAY" --volume="/etc/passwd:/etc/passwd:ro" -it REPO:TAG /bin/bash -
Bandoos about 4 yearsit may also be necessary to allow connections to X from any host with
$ xhost +
-
Admin about 4 yearsrunning this over ssh, I had to add "--network host" to the docker run command as well. (to avoid "Error: Can't open display: localhost:10.0")
-
MrR almost 4 years
--net=host
is a bad idea as now if you open a port in the container it will be open in the host as well... -
MrR almost 4 years"Create the X11 Unix socket and the X authentication file" doiesn't create any files, it just defines variables?
-
dragon788 almost 4 yearsI don't think
xhost +
is more private, I think that actually opens up the server to any connection per the second highest voted answer. stackoverflow.com/a/25280523 -
eosphere about 3 yearsI followed the instructions given in medium.com/@SaravSun/… and it worked flawlessly with this command line :
sudo docker run --net=host --env="DISPLAY" --volume="$HOME/.Xauthority:/root/.Xauthority:rw" xeyes
-
Leopd about 3 yearsI didn't have a
~/.Xauthority
file for some reason, so I had to generate one by runningxauth generate $DISPLAY . trusted
-
ai2ys almost 3 years@Nick what kind of modifications were required in the dockerfile? Like mentioned in the previous comment I am getting the same error "unable to find user <username>: no matching entries in passwd file."
-
Nick almost 3 years@ai2ys, I think I must have added users to the container.
-
Artur Opalinski over 2 years"If you run xauth list on the host and container, with the same Xauthority file, you'll see different entries listed. " -> if you REALLY see this, then this is a bug. "The SSH server running on a remote machine emulates its own X server." -> no, it does not. It only opens a TCP port on the remote end and forwards the traffic to the local end, where an X server is needed to process it.
-
Admin about 2 yearsYour Dockerfile instructions don't working, be cause I build the instruction and can't start de container :( # nano Dockerfile (and put the information) # docker build -t mycontainervnc . # docker run -p 5900:5900 --name vnc -e HOME=/ mycointainervnc x11vnc -forever -usepw -create # and not working :(