Running GUI apps with Docker for remote Access

In this blog post, we will explore how to start and access a Linux Docker image with a graphical desktop and access it remotely using VNC.

In the course of the blog post, we will

  • search for an appropriate Docker image on Docker hub,
  • download and start it as a daemon,
  • test the VNC access and
  • make sure the container starts automatically as soon as the Docker host is booted.

Note that if your Docker host is running X11 and local access to the container desktop is sufficient, there are solutions without VNC server; see e.g. the blog of Fabio Rehm. In our case, we would like to be more flexible and run the Docker host on a remote infrastructure (AWS in my case). We will see that this is not a complex task either, if we re-use existing Docker images from Docker hub.

Step 1: find an image, which offers the features you need

I am looking for an Ubuntu Docker image with access to a graphical desktop, with the following features:

  • Must have:
    • remote access to the graphical interface
    • access is possible via VNC client
    • should work also on Docker hosts without X11, e.g. a Linux server w/o X11
  • Nice to have:
    • desktop access via web

I have searched Docker images with keyword “vnc” on the Docker Hub. I have found 2 popular images (11 stars each, > 1k downloads):

Note: while writing this post, I had failed to sort based on downloads or stars. Otherwise, I would have found the images dorowu/ubuntu-desktop-lxde-vnc or vvoyer/docker-selenium-firefox-chrome with 44 stars each and 10k+ downloads.

  • kaixhin/vnc
    • LXDE desktop
    • TightVNC server
    • Firefox browser
  • consol/ubuntu-xfce-vnc
    • Desktop environment Xfce4
    • VNC4Server (default VNC port 5901)
    • noVNC – HTML5 VNC client (default http port 6901)
    • Java JRE 8
    •  Browsers:
      • Mozilla Firefox + Java Plugin
      • Google Chrome (Java-Plugin is no longer supported)

The latter image has a more elaborate readme file, so I have chosen this one (moreover, I know someone from Consol, which is a second reason to choose that image).

Step 2: Pull the image (optional)

Note that this step is optional, since a docker run command will automatically pull the image, if it is not found in the local image repository.

I am using the Docker host on AWS I have created in this blog post. However, the procedure should work on any Docker host. On the Docker host, run

sudo docker pull consol/ubuntu-xfce-vnc

Step 3 (optional): Get acquainted with the image

In order to get acquainted with the image,  I have started the docker image in interactive mode (-it) with a bash shell:

sudo docker run -it -p 5901:5901 -p 6901:6901 consol/centos-xfce-vnc bash

I have received many CRITICAL xfce4-session error messages during startup. However, even without manually starting the server, the graphical desktop as well as the VNC server were started automatically and they seem to work fine, as we will see below. Moreover, the CRITICAL messages might have been caused by using “bash” as a command option of the docker run command. This will overwrite the CMD option “–tail-log” of the image’s Dockerfile.

In my case, I am accessing the instance via Internet. In order to find the public IP address of the instance, I could access the AWS management console. However, I prefer to show a method that works in other environments as well. The Docker image has installed curl and wget, so we just issue the following wget command:

# wget -qO -

The returned information now can be used to access the system via the noVNC http access, in our case via


That was not hard.

Step 4: start the Docker image in detached mode (option -d) with automatic start of the Docker container after bootup of the Docker host:

# sudo docker run -d -p 5901:5901 -p 6901:6901 --restart=always consol/ubuntu-xfce-vnc

In this case, I will not get a console session to the container, but I still can connect to the container via VNC. For that, retrieve the public IP address with the following command again

wget -qO -

And from the answer, construct the access URL


Here “host” must be replaced by the IP address you have received with the wget command.

Step 5: verify the automatic restart of the daemon

The –restart=always option of the docker run command should make sure the docker container is always up and running as soon as the docker host is up. Let us test this now. On the Docker host console, we want to understand, whether the docker run with the –restart=always options survives a reboot of the Docker host. For that, we perform the command

sudo reboot

After a short time (< 4 minutes), we can re-connect to the Docker host image and check the Docker containers. We see that the Docker image has been started automatically:

ubuntu@ip-172-31-20-52:~$ docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED              STATUS              PORTS                                            NAMES
a176d8e933c6        consol/ubuntu-xfce-vnc   "/root/scripts/vnc_st"   10 minutes ago       Up About a minute>5901/tcp,>6901/tcp   agitated_mestorf

Appendix A: Customizations of the Consol/Sakuli image

1) enable bash command completion in the Terminal (using Tab)

After a long time, I have remembered this post and wanted to make use of the Consol/Sakuli docker image. There, I found out that neither cut&paste nor the Tab command completion in the terminal window has worked. I have found a workaround describes as last comment on this forum (scroll down to the post from October 23rd, 2012, 07:09 PM):

Step A.1.1 edit ~/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-keyboard-shortcuts.xml
Step A.1.2 find the line
<property name=”&lt;Super&gt;Tab” type=”string” value=”switch_window_key”/>
and change it to
<property name=”&lt;Super&gt;Tab” type=”empty”/>
Step A.1.3 reboot or whatever and then tab will work properly!

-> in case of a Docker image, we can perform following commands

docker stop CONTAINERID
docker start CONTAINERID

where CONTAINERID must be replaced by the container ID you find in the docker ps command. Now you can reconnect via VNC (e.g. refresh the noVNC page in the browser) and the tab will work.

Possible Next Steps

Up to now, we have tested an off-the-shelf Docker image in order to get remote access to a graphical Linux Docker container. However, most likely you will need your own (graphical) software installed on the container. Instead of installing the software every time after you have started the Docker container, it makes sense to build your own Docker image that contains the software you need.

Step 6.1: On Github, fork the build files for the Consol VNC image

Since we intend to change the Dockerfile, we will fork the Consol VNC Dockerfile & Co from their Git Source repository. As with every automatically built Docker image, the link to the source repository can be found on Docker Hub. As a GitHub user, fork the repository.

Step 6.2: test the docker build

TODO: test how to build the docker image from the repository

Step 6.3: adapt the Dockerfile and re-build the image

TODO: Choose some graphical software, e.g. the NetBeans SW, add the apt-get commands to the Dockerfile and build the docker image as shown in the blog of Fabio Rehm.

Step 6.4:test the new image

TODO: start and connect to the image, start the software and take a screeshot


We have shown how easy it is to load an existing Docker image from Docker Hub and remotely access its graphical desktop, if the image has VNC installed.


4 thoughts on “Running GUI apps with Docker for remote Access

  1. Hello there! Great write-up! Giving this a shot and it seems to be working so far!

    Just one nit-picky tweak to the post… In the heading for Step 4, the -d isn’t “daemoning” the container. That flag simply runs the container in detached mode. The “–restart=always” is what is making it start up automatically the next time the Docker daemon starts. Figured I would just point that out in case it ends up confusing someone.


    1. @Michael,
      great, if the article is of any help. And thanks a lot for the feedback about the ‘-d’ option. I have changed the wording in Step 4 accordingly. I need more feedback of that sort: this is the best way of improving the article.


    1. I was running the instance on AWS, so I had to access it from the Internet. Therefore, I had to find out the public accessible IP address, which differs from the local IP address you get with the ifconfig command you have used. In your case, you are probably running the container locally, so an ifconfig on the docker host will do the job.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s