Using Docker to Run Twitter in a Firefox Container

By on 05/11/2015.

docker-bannerDocker is all the rage of late. It fits nicely in the cloud and dev/ops world. It’s getting tons of VC backing. But there are other uses for it. For instance, ever see a device out in the real world running an application that is stuck in a Windows BSOD? Did you know that as of April 2014, 95% of ATMs were still running Windows XP?

Or maybe you just want to set up a kiosk with a web browser at a fast food restaurant to allow people to apply for jobs.

What if you could run an application without depending on an OS and have that application be easily configurable, repeatable and rolled out quickly across multiple devices? Couldn’t Docker do this?

As a matter of fact, Docker already does stuff like this in some businesses, where it can run platforms as a service (PaaS). For more information on what use cases Docker is already seeing, check out their use cases page.

If you are new to Docker, you can use their handy tutorial to give it a test run.

The goal of this blog is to show that you can quickly and easily run a container to do something as simple as sending a tweet from Twitter from a container – the ultimate subtweet! I used a container running Ubuntu with VNC and Firefox installed. There are other ways to do this (such as Selenium).

It’s a simple proof of concept, and, admittedly, pretty rudimentary. But it’s a start!

Getting started

The first thing you have to do, of course, is install Docker. My lab is running on Centos7, so I use yum to install it.

# yum install docker*

# docker version
Client version: 1.5.0-dev
Client API version: 1.18
Go version (client): go1.3.3
Git commit (client): fc0329b/1.5.0
OS/Arch (client): linux/amd64
Server version: 1.5.0-dev
Server API version: 1.18
Go version (server): go1.3.3
Git commit (server): fc0329b/1.5.0
OS/Arch (server): linux/amd64

Also, I want to make sure I have a Docker login/account. That way, I can push new images up when I finish.

After I get set up, I search to see if someone already has done what I wanted to do. Turns out, there are plenty of instances of Firefox that turn up, as well as VNC. But I want to learn a bit while I do this, so I took an existing container and modified it slightly to use a newer Ubuntu image and customize the browser a bit using Mozilla CLI.

The base template I used was from a repository found here: https://registry.hub.docker.com/u/creack/firefox-vnc/

I found the Dockerfile in a web search here: http://stackoverflow.com/questions/16296753/can-you-run-gui-apps-in-a-docker-container

I took that Dockerfile and edited it to look like this:

# cat Dockerfile
# Firefox over VNC
#
# VERSION 0.1
# DOCKER-VERSION 1.5

from ubuntu:14.10
# 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 -fy 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 -height 1200 -width 1600 -url twitter.com" >> /.bashrc'

What now?

Right now, the container doesn’t exist. All I have is a Dockerfile. To get a container image, we have to build it. When I run a build, it will take the information from the Dockerfile and do the following:

  • Grab the Ubuntu container image
  • Run updates
  • Install and configure VNC, Firefox and xvfb
  • Autostart Firefox

The build itself took about 2 minutes to run.

# docker build --rm -t parisi/firefox-ubuntu-vnc .
Sending build context to Docker daemon 2.56 kB
Sending build context to Docker daemon
Step 0 : FROM ubuntu:14.10
Trying to pull repository docker.io/ubuntu ...
d191563ad36b: Download complete
9802b3b654ec: Download complete
14975cc0f2bc: Download complete
8d07608668f6: Download complete
Status: Downloaded newer image for docker.io/ubuntu:14.10
 ---> d191563ad36b
Step 1 : RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list
 ---> Running in e42484e4a85c
 ---> cf7285e557d0
Removing intermediate container e42484e4a85c
Step 2 : RUN apt-get update
 ---> Running in 683f2d3dc136
Ign http://archive.ubuntu.com precise InRelease
Get:1 http://archive.ubuntu.com precise Release.gpg [198 B]
Get:2 http://archive.ubuntu.com precise Release [49.6 kB]
Get:3 http://archive.ubuntu.com precise/main amd64 Packages [1640 kB]
Get:4 http://archive.ubuntu.com precise/universe amd64 Packages [6167 kB]
Fetched 7857 kB in 17s (438 kB/s)
Reading package lists...
 ---> 0e2ced490732
Removing intermediate container 683f2d3dc136
Step 3 : RUN apt-get install -fy x11vnc xvfb firefox
 ---> Running in a45496138436
Reading package lists...
Building dependency tree...
Reading state information...
The following extra packages will be installed:
 [packages]
Suggested packages:
 [packages]
Recommended packages:
 [packages]
The following NEW packages will be installed:
 [packages]
0 upgraded, 126 newly installed, 0 to remove and 0 not upgraded.
Need to get 65.5 MB of archives.
After this operation, 189 MB of additional disk space will be used.
[gets a bunch of stuff]
Fetched 65.5 MB in 1min 9s (940 kB/s)
[unpacks a bunch of stuff]
[sets it up]
Processing triggers for libc-bin (2.19-10ubuntu2.3) ...
 ---> 16bd3eac67a8
Removing intermediate container a45496138436
Step 4 : RUN mkdir ~/.vnc
 ---> Running in fe43a55fadcc
 ---> b2d2a545b667
Removing intermediate container fe43a55fadcc
Step 5 : RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
 ---> Running in 956afa9ea4b7
stored passwd in file: /root/.vnc/passwd
 ---> 852c86063505
Removing intermediate container 956afa9ea4b7
Step 6 : RUN bash -c 'echo "firefox -height 1200 -width 1600 -url twitter.com" >> /.bashrc'
 ---> Running in 4f411cfe38bb
 ---> ed8d7cb5eeb1
Removing intermediate container 4f411cfe38bb
Successfully built ed8d7cb5eeb1

Now that it’s built, it shows up in docker images. Notice how Ubuntu also shows there:

# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
parisi/firefox-ubuntu-vnc latest ed8d7cb5eeb1 4 minutes ago 383.9 MB
docker.io/ubuntu 14.10 d191563ad36b 6 days ago 194.4 MB
docker.io/ubuntu utopic d191563ad36b 6 days ago 194.4 MB
docker.io/ubuntu utopic-20150427 d191563ad36b 6 days ago 194.4 MB

Testing the image

Once an image is built, it needs to be tested to ensure it actually works the way we want it to. To do that, we run the image using “docker run.” When I do that, the VNC server starts on port 5900:

# docker run -p 5900 -e HOME=/ parisi/firefox-ubuntu-vnc x11vnc -forever -create
###############################################################
# big long warning
###############################################################
PORT=5900
07/05/2015 15:11:15 x11vnc version: 0.9.12 lastmod: 2010-09-09 pid: 1
07/05/2015 15:11:15
07/05/2015 15:11:15 wait_for_client: WAIT:cmd=FINDCREATEDISPLAY-Xvfb
07/05/2015 15:11:15
07/05/2015 15:11:15 initialize_screen: fb_depth/fb_bpp/fb_Bpl 24/32/2560
07/05/2015 15:11:15
07/05/2015 15:11:15 Autoprobing TCP port
07/05/2015 15:11:15 Autoprobing selected port 5900
07/05/2015 15:11:15 Listening also on IPv6 port 5900 (socket 5)
07/05/2015 15:11:15

The VNC desktop is: 54b31df70c29:0

I can see that the container ID is 54b31df70c29. This is confirmed via “docker ps”:

# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
54b31df70c29 parisi/firefox-ubuntu-vnc:latest "x11vnc -forever -cr About a minute ago Up About a minute 0.0.0.0:49192->5900/tcp angry_pike

I see that the port being used is 49192. I can confirm that via “docker port.”

# docker port 54b31df70c29
5900/tcp -> 0.0.0.0:49192

From here, I can open any VNC client and connect to my CentOS IP address on the specified port. In my case, I use Chrome’s VNC browser extension.

Once connected, the running docker image shows that information:

07/05/2015 15:15:59 Got connection from client 10.62.194.166
07/05/2015 15:15:59 other clients:
07/05/2015 15:15:59 incr accepted_client=1 for 10.62.194.166:53643 sock=6
07/05/2015 15:15:59 wait_for_client: got client
07/05/2015 15:15:59 Client Protocol Version 3.8
07/05/2015 15:15:59 Protocol version sent 3.8, using 3.8
07/05/2015 15:15:59 client progressed=1 in 4/3 0.005678 s
07/05/2015 15:15:59 client_set_net: 10.62.194.166 0.0267

Publishing the image

Now that I’ve confirmed the image works, I can publish it for public consumption.

First thing I do is:

  • Log in to my Docker account
  • Tag and push the image to the registry
# docker login
Username (parisi):
Login Succeeded

# docker tag ed8d7cb5eeb1 parisi/firefox-ubuntu-vnc
# docker push parisi/firefox-ubuntu-vnc

Do you really want to push to public registry? [Y/n]: Y
The push refers to a repository [docker.io/parisi/firefox-ubuntu-vnc] (len: 1)
Sending image list
Pushing repository docker.io/parisi/firefox-ubuntu-vnc (1 tags)
9802b3b654ec: Image already pushed, skipping
14975cc0f2bc: Image already pushed, skipping
8d07608668f6: Image already pushed, skipping
d191563ad36b: Image already pushed, skipping
cf7285e557d0: Image successfully pushed
0e2ced490732: Image successfully pushed
16bd3eac67a8: Image successfully pushed
b2d2a545b667: Image successfully pushed
852c86063505: Image successfully pushed
ed8d7cb5eeb1: Image successfully pushed
Pushing tag for rev [ed8d7cb5eeb1] on {https://cdn-registry-1.docker.io/v1/repositories/parisi/firefox-ubuntu-vnc/tags/latest}

Now my repository is public here: https://registry.hub.docker.com/u/parisi/firefox-ubuntu-vnc/

Publishing the image allows me to share my work with others, as well as have a cloud-based location for the lightweight image (less than 500MB!) that can be pulled from any client running docker anywhere in the world. And the best part? It’s FAST.

Then I clean up:

  • Stop the running image (from new SSH session using “docker stop”)
  • Clean up the existing images and processes (this shows a great way to do that quickly)
  • I clean up the images to ensure I know what I’m doing is working and there are no lingering images out there helping me.

After I clean up, I check to make sure nothing is lingering:

# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

Now I can pull the image down to ensure it works:

# docker pull parisi/firefox-ubuntu-vnc
Trying to pull repository docker.io/parisi/firefox-ubuntu-vnc ...
ed8d7cb5eeb1: Download complete
9802b3b654ec: Download complete
14975cc0f2bc: Download complete
8d07608668f6: Download complete
d191563ad36b: Download complete
cf7285e557d0: Download complete
0e2ced490732: Download complete
16bd3eac67a8: Download complete
b2d2a545b667: Download complete
852c86063505: Download complete
Status: Downloaded newer image for docker.io/parisi/firefox-ubuntu-vnc:latest

# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
docker.io/parisi/firefox-ubuntu-vnc latest ed8d7cb5eeb1 36 minutes ago 383.9 MB

Pulling the new image took only 35 seconds!

Now, I run the image.

# docker run -p 5900 -e HOME=/ parisi/firefox-ubuntu-vnc x11vnc -forever -create

That took 1 second!

Imagine being able to pull, stand up and run an entire OS container and application in less than 40 seconds… How useful could that be?

The Ultimate Subtweet

Now that I have a publicly available container that runs Firefox to feed my Twitter addiction, I can now show that it works.justin-vnc

justin-vnc-connectjustin-vnc-twitterjustin-vnc-twitter-logged-in

This is the link to the tweet I sent from my Docker container:

That’s it. Fast. Simple. Accessible. Open.

No wonder so many people love this stuff…

Lastly, be sure to check out my post on Using NFS with Docker, and where it fits in!

Justin Parisi
Tech Mktg Engineer at NetApp
Justin is a Tech Marketing Engineer for all-things NFS around Data ONTAP at NetApp. He is a VMware vExpert, Cisco Champion, and a member of the NetApp A-Team. He also enjoys comic books, video games, photography, music, film, and current events/politics.

One Comment