Ops are from Mars, Devs are from Venus: Practical Docker – Understanding the Dockerfile

March 27th, 2015 by

docker_logoSince we have decided to tackle some Docker learning, and see about using this exciting container system as a platform to host our applications, we should back up a little bit to see why we are doing this. Remember, the reason that Docker is becoming so popular is that it provides agility to deploy your applications. As you’ve seem with our first example of a simple Docker deployment, this was still very manual.

This seems like the ideal spot to take a look at how to build a little more repeatability into our Docker deployment. By making the deployment more programmatic, we ensure that it will be consistent every time we use the same method. This is where we begin by looking at something called the Dockerfile.

What can a Dockerfile do?

The advantage to a Dockerfile is that it provides the ability to run a series of commands and configuration parameters for you. The same way that we chose a single container to run and we used interactive commands to deploy applications into it can be achieved with a Dockerfile. The Dockerfile is a script, which can and should be created as a readable deployment recipe for your container.

Much like other simple scripting languages, there are a variety of commands, parameters, and we can comment throughout in order to increase the readability for now and later. With our previous sample, we had the Ubuntu container deployed and we also installed the Apache web server inside that Ubuntu container.

Let’s take a look at what it would take to do the same thing with our Dockerfile instead.

Building the Dockerfile

Our example is light weight, and needs only two commands to emulate what we did in our first blog. We begin with the FROM command, which is what gives us the base image to work from. When we did this manually, we simple launched the container and gave ubuntu as the source. This time, we create a file with a meaningful name and we can use it to create the recipe for our build.

Since we want Ubuntu again, we will use this command in the Dockerfile to do that:

FROM ubuntu

It really is just that simple. You’ll recall that we did a few other steps to update our Ubuntu container, install Apache, and to create the home page for our sample Hello World application.

When done manually, we launch the container, then install and configure the components.  In a Dockerfile, we just use the RUN command and issue the same command lines that we did manually.

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

That takes care of the update and download. Next we create our landing page:

RUN echo “Hello Docker World” > /var/www/html/index.html

That’s our sample page all set up, and we just have to take care of the next step which is to open up the networking on the container to allow inbox access to port 80 which is for HTTP. This is done using the EXPOSE command.

EXPOSE 80

Now the final step is to make sure that the Apache web server is running at boot. This is a rather crude method, but let’s have it launch as part of the bash shell for an interactive login. I’ve made the choice to do this in order to cut down on the amount of text in our sample Dockerfile. In future examples we will do much more elegant configurations for service management.

RUN echo /usr/sbin/apachectl start >> /etc/bashrc

Now that we have our full Dockerfile built, this is what it will look like with comments also added in using the hash (#) symbol:

dockerfile

Time to build our new container!

Building and Launching from the Dockerfile

The build process is done using the sudo docker build command. We will use the -t ubuntu-apache . parameters which mean that we are tagging it as ubuntu-apache and the period indicates to use a Dockerfile in the current folder.

docker-build

We see that it creates temporary containers, and if you haven’t already downloaded the Ubuntu container image, there will be some additional steps to download to the local repository.

The container shows as successfully built, so now we run using the sudo docker run command and we will pass the parameters —name apache_test -i -t ubuntu-apache which runs an interactive container and will name it apache_test. The container will be build from the tagged ubuntu-apache container image.

docker-run

We see the IP address shown in the console because the Apache started up with a warning. Testing the Apache build is as simple as using our curl http://localhost command:

docker-curl-apache

Not only can we do this from the console within our container, but we can also detach from it using the key sequence of Ctrl-P Ctrl-Q and that puts us back at the shell with the container still running.

Because we know the IP address (172.17.0.25 in our example), we can use the curl command to run curl http://172.17.0.25 from our host:

docker-detach-curl

Just like that we have build our system with Apache installed and some other commands running. The use of the Dockerfile means that we will have a consistent, reusable build process that will come in handy later on.

Time to clean up after ourselves, so let’s check the container we have running to be sure we can stop and remove it. Just run the sudo docker ps -a

docker-ps

We can see the container ID is 40bfb2fb62e2 in our example, so our last steps are to stop and remove the container with the sudo docker stop 40bfb2fb62e2 and sudo docker rm 40bfb2fb62e2 commands:

docker-cleanup

This is really a rudimentary example, but shows that we can start small and build slowly. We have come from manually launching the container to a scripted build and launch.

It looks like we are ready to ramp up a little more and get to some more complex examples hopefully. This will also give us a chance to start to think like a developer and embrace the DevOps pro inside all of us. As Dr. Seuss once wrote “Oh the places you’ll go!”

Leave a Reply

Your email address will not be published. Required fields are marked *