Docker – The Future

Let’s face it ! – Its all about APPLICATIONS and DATA.

There were times when we first had bare metal servers and cared about OS – probably one each for application. Then we optimized and moved on to VM’s – Well learn what ? Sure VM’s were a step up from the bare metal servers and offered some optimization, however we still don’t have the utilization optimized yet (smile) Welcome to Docker !! The closest to as lightweight as we can get for an app container (well we mean, everything that app needs to run successfully – fs, network, pid space, runtimes…). Docker aligns with micro service architecture very much.

As of now, Docker daemon works only on linux Kernel and let’s hope that Windows Kernel will allow dockerization soon (wink). There are tweaks, like windows runs inside a linux docker , that runs on a linux kernel, but you can see how convoluted that is.

Docker ideology?

ONE PROCESS/MICRO-service PER CONTAINER (Well it is possible to have multiple processes, but that is the ideology)

Why does it matter ?

Well think about it. What does an app really need from an OS perspective. It needs a user space (contrast with kernel space). So namespaces is what we are referring to. The high level namespaces required for an app are a) root file system b) Process ID namespace c) network namespace.

The three namespaces is offered by OS Kernel to the app. On a bare metal, where we launch VM’s, the VM’s virtualize the underlying details to the app. And the VM’s still occupy a large amount of memory and space. What if we can

1) Create instance of Kernels (root file system, pid namespace, network namespace etc.)

2) Think from the perspective of what app needs (Not what clunky OS offers)

3) Light weight containers that are app focused and sandboxes for development environment

4) Built once and magically work on any flavor of linux (For now linux, windows always plays catch up ya !)

  • Namespaces let us carve up things like the process tree, the filesystem, networking etc so that each container gets its own unique and isolated view of each – basically making a container think its got PID 0 and the root filesystem (/) and not knowing about other containers on the system….
  • croups let us control resource utilisation for containers
  • Capabilities let us get very granualr with container privileges

Anyways, this post here shows how we can spin up a docker image, that becomes the manifest for the ‘n’ containers that represent our micro-service (in this case we choose an example of apache server)

Docker Ecosystem 

Docker_ecosystem

Requirement

Our requirement here is to build a container from an image that already has done the following

  • Spin up a fresh OS (in this case an ubuntu image 15:04 pulled from docker hub)
  • aptitude update (to refresh the cache and build the apt-get registry sources list)
  • install apache, apache-utils
  • clean any tmp files that might exist before apache is run
  • EXPOSE port 80 
  • START apache server

As you can see I highlighted the last two instructions, because they are run time (meaning they make sense only when the container is active). The rest of the instructions are BUILD time instructions i.e. when constructing our docker image, the instructions are executed (by building layers on top of OS). The significance is to say, that once we have an image, ONLY the RUN time instructions become relevant. The BUILD instructions are guaranteed as they are part of the image.

This concept of BUILD vs. RUN time instructions make a powerful combination, because when we want to replicate micro-service at a large scale, we spin up multiple containers based off the docker image. And we can be assured that all of them are EXACT replicas.

DOCKER Image

Let’s first see how the docker image is constructed

FROM ubuntu:15.04
RUN apt-get update && apt-get install -y \
 apache2 \
 apache2-utils \
 vim \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
EXPOSE 80
CMD ["apachectl","-D","FOREGROUND"]

1) FROM – This instruction is to say that we start with the base image ubuntu 15.04

2) RUN – This is a build instruction. You can see that we are installing a bunch of packages

3) EXPOSE – We expose port 80

4) CMD – We run apache and we would like to run it in the foreground, so that the container doesn’t exit (There are many strategies we can use to keep the process running, in this case the shell)

The image constructed from the above docker file is as below.

We can see that it is approx. 285MB – We have an entire OS packed into 285MB yep. entire OS with all necessary platforms and application dependent libraries, so that we can avoid the famous statement

It worked on my machine, but it doesn’t work on yours

The bottom right 20.15MB is coreos and we can see how lightweight the container can get. Anyways, we will talk about coreos in a separate post.

Docker Container

Time to fire up a container from the image.

docker run -d --name=mywebserver webserver

As you can see it instantly fires up a container and the cursor returns back to host os. We can type “docker ps” to see the running containers and indeed we can see that the container is running. Every time a container is fired up, docker assigns a GUID to it. Next up, let’s see how we can enter the container.

Method 1:

The simplest and easiest way to enter the container, meaning get to a tty on a shell is use docker exec

docker exec -it mywebserver /bin/bash

This will land your inside the container on a bash shell prompt

As you can see we are now inside the container and if we inspect the processes, we can indeed see that apache is running.

If you want to step outside a container just hit Ctrl + P + Q

Method 2:

docker-enter mywebserver

Method 3:

docker inspect <container_id> | grep Pid
nsenter -m -u -n -p -i -t <pid> /bin/bash

Here we first grab the pid of the container (pid as assigned by the docker host to the container). Using that pid , we use nsenter command. nsenter command is very interesting and the switches are as follows

m – enter mount namespace

u – enter uts namespace

n – enter network namespace

p – enter process namespace

i – ipc namepace

t- target pid

Apace web server

Finally lets check that the apache web service is indeed serving pages out of the container.

We first grab the ip of the container, then hop out of container, then from docker host, we call apache default home page.

Voila! Indeed we see that the html page back back.