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.
- LXDE desktop
- TightVNC server
- Firefox browser
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/ubuntu-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 http://ipinfo.io/ip -qO - 22.214.171.124
The returned information now can be used to access the system via the noVNC http access, in our case via http://126.96.36.199:6901/vnc_auto.html?password=vncpassword:
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 a176d8e933c66d3edc58eb9f2ba1c45175ff6b6878210f1b97ed8c3343670044
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 http://ipinfo.io/ip -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
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 0.0.0.0:5901->5901/tcp, 0.0.0.0:6901->6901/tcp agitated_mestorf ubuntu@ip-172-31-20-52:~$
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=“<Super>Tab“ type=“string“ value=“switch_window_key“/>
and change it to
<property name=“<Super>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.
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.
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.
# wget http://ipinfo.io/ip -qO –
Why are you using this command?
I’m running the bash command as described, so on the client I ran ifconfig and got a different ip
which i than used in the url as shown
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.
Just a typo: In step 4, you typed centos instead of ubuntu:
sudo docker run -it -p 5901:5901 -p 6901:6901 consol/centos-xfce-vnc bash
Hi Alex, thanks for your hint. I will have a look.
Hi Alex, thanks a lot. I have corrected the typo. Best Regards, Oliver
Great tutorial. I would like to run multiple containers on a host with the docker mage described here and would like to know if anyone can tell me how to assign each container a different public ip address .So it can be accessed from remote (outside the local network).
So i end up with something like:
container1 = vnc://container1.domain.com
container2 ) = vnc://container2.domain.com
container 3 ) = vnc://container3.domain.com
Where every application running in the containers can use the same port so for e.g i don´t have to bind each VNC Server to a different Port.
Hi Roman, if you are referring to a situation with 3 puplic IP addresses, you need to configure your NAT firewall to map your public IP+port to a single private IP and different ports of the Docker host, which can map those different ports to the same container ports. If you are referring to a situation with no NAT and a Docker host with 3 IP addresses, I do not know, how to map it without googling and testing to be honest. I never had this situation. But maybe you have found out already? If yes, please let us know. Best Regards, Oliver