Day 21: Docker–The Missing Tutorial

A couple of months ago, Red Hat announced a partnership with dotCloud on their Docker technology. I did’t have the time then to learn about Docker so today for my 30 days challenge I’m learning what Docker is all about.

This blog post does not cover OpenShift’s plans for using Docker in the future. Please read the blog post by Mike McGrath called Technical Thoughts on OpenShift and Docker. Also read this stackoverflow question to understand how Docker compares to OpenShift.

What is Docker?

Docker provides an envelope (or container) for running your applications. dotCloud started it as a side project and open sourced it earlier this year. Docker received a lot of attention and buzz so dotCloud renamed itself to Docker Inc. Docker is mostly written in Go and acts as plumbing over LXC (LinuX Containers), allowing developers to work with higher level concepts.

Docker extends Linux Containers, or LXC, with a high level API providing a lightweight virtualization solution that runs processes in isolation. Docker utilizes LXC, cgroups, and the Linux kernel itself. Unlike traditional virtual machines, a Docker container does not include a separate operating system, instead it relies on the operating system’s functionality provided by the underlying infrastructure. There is an answer on stackoverflow which clearly details out all the features provided by Docker over plain LXC.

Docker acts as a portable container engine. It packages the application and all its dependencies in a virtual container that runs on any Linux server. This helps enable flexibility and portability on where the application can run, whether on premise, public cloud, private cloud, bare metal, etc.

Docker consists of:

  1. Docker server daemon which is responsible for managing all the containers
  2. Docker command line client which controls the server daemon.
  3. Docker image repository is the place to find and browse docker images. It is available at

Why should I care?

Docker solves the problem of shipping code from one machine to another. It attempts to make the software shipping process more reliable and automated. Docker containers are portable to any operating system running Docker.

Learn more about how the Fedora Project is embracing Docker.

But I already use VMs

Today the only viable for shipping an application reliably is Virtual Machines(or VMs). Virtual machines are common these days but they are level and provides the full operating system with them.The problem with VMs is that they ship too much. They package lot of information which not required like the hard drive, virtual processors, and network interfaces. VMs also takes a long time to boot, and consumes significant amount of memory and CPU.

Docker on the other hand is lightweight, almost comparable to starting a regular process. Running container is fast and building an image and snapshotting the filesystem is fast too. Docker works in virtualized environments like EC2, or RackSpace VMs. The preferred way to use Docker on Mac and Windows is using Vagrant. Docker’s purpose is to function as a VM with faster start up, consuming less resources.

Is it like Vagrant?

I was confused whether I should use Vagrant or Docker for creating a sandboxed environment for my next project. The answer is still the same.

Docker is performs better and has less overhead compared to Vagrant. The environment Vagrant provides is still the virtual machine which is dependent on Virtual Box. Read this answer on stackoverflow for more details.

Oh No! Another application packaging system

When I first read that Docker packages the application I got confused. Why do we need another packaging system? I already package my Java applications as JAR or WAR. After reading more about Docker I understood the meaning of Docker application package. Docker sits between the virtual machine and your application package like WAR or JAR. The virtual machines on the one hand are heavy weight as they ship more than what is required. On the other hand, the application code packages are lightweight and do not ship enough information to reliably run the application. Docker provides best of both worlds.

In Docker, application package means a package containing the application code and associated deployment environment. For example, in Java we normally package our web applications in a WAR file. The war file package is a minimalistic package since it only contains the application code. But Java applications rely on the deployment environment to run effectively.

Other chanllenges we run into:

  • The deployment environment is different from development environment. The application was developed using Java 7 and the deployment environment has OpenJDK Java 6.
  • The application was developed on a Mac and deployed on RHEL.
  • System libraries vary between systems resulting in different application behavior between development and staging environments.

Docker helps alleviate these problems by packaging the application and its dependencies.

Getting Started with Docker

Install Docker on a Fedora machine using the instructions mentioned in this blog.

$ vagrant up
$ vagrant ssh

And then install the docker fedora image

$ sudo docker pull mattdm/fedora

The above command will download the Docker fedora image from

After installing Docker Fedora image, we can list all the images using the following command.

$ sudo docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
shekhargulati/node_image_007   latest              e12b3054d981        50 minutes ago      470.3 MB (virtual 601.8 MB)
mattdm/fedora                         12.04               8dbd9e392a96        7 months ago        131.5 MB (virtual 131.5 MB)

The first image listed is the one that I have created. It packages NodeJS along with Express Framework. The second image is the stock docker fedora image.

Now lets run a shell within a docker container.

$ sudo docker run -t -i -p 3000 mattdm/fedora /bin/bash

Now we are inside Docker container. We can list all the files using ls command.

Now we will create following directory structure /home/shekhar/dev.

$ mkdir -p home/shekhar/dev
$ cd home/shekhar/dev

Now I will install NodeJS. Run the following commands to install Node on Fedora Docker image.

$ sudo yum install npm

The above shown commands will install nodejs on the Fedora Docker image.

Next we will install Express framework.

$ npm install express -g

Now we can create a new express application and run it.

$ express myapp
$ cd myapp
$ npm install
$ node app.js

The above will start the NodeJS Express application at port 3000.

Now open another command line tab, list all the docker processes.

$ sudo docker ps
CONTAINER ID        IMAGE                                 COMMAND             CREATED             STATUS              PORTS                     NAMES
4a5715a915e5        mattdm/fedora   /bin/bash           5 minutes ago       Up 5 minutes>3000/tcp   red_duck

NOTE: port 3000 is bound to port 49157 on the host machine. You can test the express application by curl as shown below.

$ curl
<!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.css"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>

Now commit the image and then push it to the Docker image registry. Before you can do that, you must register with the Docker registry

$ sudo docker commit 4a5715a915e5 shekhargulati/node_image_007
$ sudo docker push shekhargulati/node_image_007

Please use your own username and image name.

So, my first image is uploaded to Docker registry

You can pull this image from registry by using pull command.

$ docker pull shekhargulati/node_image_007 

That’s it for today. Keep giving feedback.

Next Steps

Comments are closed.