December 15, 2015

Getting Started with Docker

cowsayDocker is the excellent new container application that is generating much buzz and many silly stock photos of shipping containers. Containers are not new; so, what's so great about Docker? Docker is built on Linux Containers (LXC). It runs on Linux, is easy to use, and is resource-efficient.

Docker containers are commonly compared with virtual machines. Virtual machines carry all the overhead of virtualized hardware running multiple operating systems. Docker containers, however, dump all that and share only the operating system. Docker can replace virtual machines in some use cases; for example, I now use Docker in my test lab to spin up various Linux distributions, instead of VirtualBox. It's a lot faster, and it's considerably lighter on system resources.

Docker is great for datacenters, as they can run many times more containers on the same hardware than virtual machines. It makes packaging and distributing software a lot easier:

"Docker containers wrap up a piece of software in a complete filesystem that contains everything it needs to run: code, runtime, system tools, system libraries -- anything you can install on a server. This guarantees that it will always run the same, regardless of the environment it is running in."

Docker runs natively on Linux, and in virtualized environments on Mac OS X and MS Windows. The good Docker people have made installation very easy on all three platforms.

Installing Docker

That's enough gasbagging; let's open a terminal and have some fun. The best way to install Docker is with the Docker installer, which is amazingly thorough. Note how it detects my Linux distro version and pulls in dependencies. The output is abbreviated to show the commands that the installer runs:

$ wget -qO- https://get.docker.com/ | sh
You're using 'linuxmint' version 'rebecca'.
Upstream release is 'ubuntu' version 'trusty'.
apparmor is enabled in the kernel, but apparmor_parser missing
+ sudo -E sh -c sleep 3; apt-get update
+ sudo -E sh -c sleep 3; apt-get install -y -q apparmor
+ sudo -E sh -c apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80
 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
+ sudo -E sh -c mkdir -p /etc/apt/sources.list.d
+ sudo -E sh -c echo deb https://apt.dockerproject.org/repo ubuntu-trusty main > /etc/apt/sources.list.d/docker.list
+ sudo -E sh -c sleep 3; apt-get update; apt-get install -y -q docker-e
The following NEW packages will be installed:
 docker-engine

As you can see, it uses standard Linux commands. When it's finished, you should add yourself to the docker group so that you can run it without root permissions. (Remember to log out and then back in to activate your new group membership.)

Hello World!

We can run a Hello World example to test that Docker is installed correctly:

$ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
[snip]
Hello from Docker.
This message shows that your installation appears to be working correctly.

This downloads and runs the hello-world image from the Docker Hub. This contains a library of Docker images, which you can access with a simple registration. You can also upload and share your own images. Docker provides a fun test image to play with, Whalesay. Whalesay is an adaption of Cowsay that draws the Docker whale instead of a cow (see Figure 1 above).

$ docker run docker/whalesay cowsay "Visit Linux.com every day!"

The first time you run a new image from Docker Hub, it gets downloaded to your computer. Then, after that Docker uses your local copy. You can see which images are installed on your system.

$ docker images
REPOSITORY       TAG      IMAGE ID      CREATED       VIRTUAL SIZE
hello-world      latest   0a6ba66e537a  7 weeks ago   960 B
docker/whalesay  latest   ded5e192a685  6 months ago  247 MB

So, where, exactly, are these images stored? Look in /var/lib/docker.

Build a Docker Image

Now let's build our own Docker image. Docker Hub has a lot of prefab images to play with (Figure 2), and that's the best way to start because building one from scratch is a fair bit of work. (There is even an empty scratch image for building your image from the ground up.) There are many distro images, such as Ubuntu, CentOS, Arch Linux, and Debian.

docker-hub
We'll start with a plain Ubuntu image. Create a directory for your Docker project, change to it, and create a new Dockerfile with your favorite text editor.

$ mkdir dockerstuff
$ cd dockerstuff
$ nano Dockerfile

Enter a single line in your Dockerfile:

FROM ubuntu

Now build your new image and give it a name. In this example the name is testproj. Make sure to include the trailing dot:

$ docker build -t testproj .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM ubuntu
---> 89d5d8e8bafb
Successfully built 89d5d8e8bafb

Now you can run your new Ubuntu image interactively:

$ docker run -it ubuntu
root@fc21879c961d:/#

And there you are at the root prompt of your image, which in this example is a minimal Ubuntu installation that you can run just like any Ubuntu system. You can see all of your local images:

$ docker images
REPOSITORY       TAG       IMAGE ID        CREATED        VIRTUAL SIZE
testproj         latest    89d5d8e8bafb    6 hours ago    187.9 MB
ubuntu           latest    89d5d8e8bafb    6 hours ago    187.9 MB
hello-world      latest    0a6ba66e537a    8 weeks ago    960 B
docker/whalesay  latest    ded5e192a685    6 months ago   247 MB

The real power of Docker lies in creating Dockerfiles that allow you to create customized images and quickly replicate them whenever you want. This simple example shows how to create a bare-bones Apache server. First, create a new directory, change to it, and start a new Dockerfile that includes the following lines.

FROM ubuntu

MAINTAINER DockerFan version 1.0

ENV DEBIAN_FRONTEND noninteractive

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2
ENV APACHE_LOCK_DIR /var/lock/apache2
ENV APACHE_PID_FILE /var/run/apache2.pid

RUN apt-get update && apt-get install -y apache2

EXPOSE 8080

CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

Now build your new project:

$ docker build -t apacheserver  .

This will take a little while as it downloads and installs the Apache packages. You'll see a lot of output on your screen, and when you see "Successfully built 538fea9dda79" (but with a different number, of course) then your image built successfully. Now you can run it. This runs it in the background:

$ docker run -d  apacheserver
8defbf68cc7926053a848bfe7b55ef507a05d471fb5f3f68da5c9aede8d75137

List your running containers:

$ docker ps
CONTAINER ID  IMAGE        COMMAND                 CREATED            
8defbf68cc79  apacheserver "/usr/sbin/apache2ctl"  34 seconds ago

And kill your running container:

$ docker kill 8defbf68cc79

You might want to run it interactively for testing and debugging:

$ docker run -it  apacheserver /bin/bash
root@495b998c031c:/# ps ax
 PID TTY      STAT   TIME COMMAND
   1 ?        Ss     0:00 /bin/bash
  14 ?        R+     0:00 ps ax
root@495b998c031c:/# apachectl start
AH00558: apache2: Could not reliably determine the server's fully qualified
domain name, using 172.17.0.3. Set the 'ServerName' directive globally to
suppress this message
root@495b998c031c:/#

A more comprehensive Dockerfile could install a complete LAMP stack, load Apache modules, configuration files, and everything you need to launch a complete Web server with a single command.

We have come to the end of this introduction to Docker, but don't stop now. Visit docs.docker.com to study the excellent documentation and try a little Web searching for Dockerfile examples. There are thousands of them, all free and easy to try.

Click Here!