One of the more important features of Docker is image content management, or image layering. Docker’s layered approach to images (or content) provides a very powerful abstraction for building up application containers. An image provides the foundation layer for a container. New tools, applications, content, patches, etc. form additional layers on the foundation. Containers are workable instances of these combined entities, which can then be bundled into it’s own image.
Docker allows you to build containers using a Dockerfile. The Dockerfile describes a base image for the build using the
FROM implicitly uses a image registry from which the base image is pulled. This can be
docker.io or some other (perhaps internal) registry.
The additional layers of a Docker container are created with directives within the Dockerfile. The
RUN directive is used to run commands in running image. Extra packages can be installed using the
RUN instruction and the Linux distribution’s package installation tool. For Fedora and Red Hat Enterprise Linux this tool is
yum. Scripts and other content can be added to the layer by using the
ADD instruction from local directories or a URL.
Once you’ve added the required additional layers to your base image to make your specific application, you can create an image and add it to a registry for re-use.
These three instructions are the basics for building containers using the Dockerfile. A simple example:
FROM fedora RUN yum install -y gcc ADD ./myprogramfiles.tar /tmp
Two Approaches to Image Building
There are two approaches to building Docker images.
Consider the following example: an administrator would like to deploy a new simple web site using Docker container technology.
The administrator decides that the image needs three components:
- Debian base image
- Apache Web server
- Web site content
The administrator can build the image in one of the two following ways:
- Interactively, by launching a BASH shell under Debian to apt-get install Apache and its dependencies, and then save the image
- Create a Dockerfile that builds the image with the web site included
The first approach involves the administrator using the Docker CLI to instantiate the base image, install the Apache web server, and then create a reusable image for later use with the web site content. In this scenario, the base Debian + Apache image can be used as a base for any project that requires those tools.
The second approach involves building a Dockerfile that uses the base Debian image, installs the needed Apache packages, and then adds the necessary content. This ensures that the entire web site is complete in one build. The image created by this build will only serve a single web site and content changes would require a rebuild.
Interactively Building a Debian Container
There is an official image called
debian (the latest Debian version) in the public Docker registry. For more information on this image and the options available, check the repository page.
To run a container with an interactive shell, run the following Docker command on the BHost VPS:
docker run -it debian bash
Then from with the docker shell environment start building your customised image
apt-get update apt-get upgrade apt-get install apache2 php5 apt-get clean exit
We now save the container as a base image in our local repository for future use using
docker commit [imagename] [userspace]/debian-php
Check you now have the two Debian images
docker images. Now we can use our own image as the basis of a website. Here is a Dockerfile to do this
## Use the image we just created FROM [userspace]/debian-php MAINTAINER [yourname] # Add the tar file of the web site ADD website_content.tar /tmp/ # Docker automatically extracted. So move files to web directory RUN mv /tmp/mysite/* /var/www/html && chown -R www-data:www-data /var/www/html COPY httpd-foreground /usr/local/bin/ EXPOSE 80 CMD ["httpd-foreground"]
You can use this simple Dockerfile as a template for building other web sites. This and the other two files required to build this tutorial can be downloaded from this GitHub directory https://github.com/blackdoginet/BHost-docker-tutorials/tree/master/createcontainer
The Docker build context passed to the daemon requires both the Dockerfile and the content for the site. The path for this build is ., but in practice you should create separate build contexts (directory) for each container.
docker build -rm -t mysite . docker run -d -p 80:80 mysite
You should now be able to visit your site at your hosts IP address
Using a Dockerfile to Build a DEBIAN Container
The administrator may decide that building interactively is tedious and error-prone. Instead the administrator could create a Dockerfile that layers on the Apache Web server and the web site content in one build.
A good practice is to make a sub-directory with a related name and create a Dockerfile in that directory. E.g. a directory called mongo may contain a Dockerfile for a MongoDB image, or a directory called httpd may container an Dockerfile for an Apache web server. Copy or create all other content that you wish to add to the image into the new directory. Keep in mind that the ADD directive context is relative to this new directory.
mkdir httpd cp mysite.tar httpd/
Create the Dockerfile in the httpd directory. This Dockerfile will use the same base image as the interactive command
FROM debian MAINTAINER A D Ministator email: firstname.lastname@example.org # Update the image with the latest packages (recommended) RUN apt-get update && apt-get upgrade -y && apt-get clean # Install Apache Web Server RUN apt-get install -y apache2 && apt-get clean # Add the tar file of the web site ADD mysite.tar /tmp/ # Docker automatically extracted. So move files to web directory RUN mv /tmp/mysite/* /var/www/html COPY httpd-foreground /usr/local/bin/ EXPOSE 80 CMD ["httpd-foreground"]
Build this Dockerfile from the new httpd directory and run it:
docker build -rm -t newsite httpd/ docker run -d -P newsite
The container build process builds a series of temporary image layers based on the directives in the Dockerfile. These temporary layers are cached so if you make modifications to the content tarball, it won’t completely rebuild and update the Debian image. Since each directive is a new layer, you could reduce the number of layers by combining the
RUN apt-get directives into a single
RUN apt-get update && apt-get upgrade -y && apt-get clean
Planning your layers will determine how many layers need to be recreated on each build of the container.
Which Approach is Right?
The approach to building images depends on why you are building the image.
Prototyping and Troubleshooting
If prototyping and trouble shooting then you probably want to do an interactive,
*inside the container* approach. Using this approach you can take notes of the history of commands used that make sense and what external files may be missing or need changes. These can be ADDed to the Dockerfile.
Complete Satisfactory Single Build
If you are satisfied with a specific image that has been built using the interactive approach and you believe it might be reused elsewhere, then it is recommended to use the single Dockerfile approach that builds it all in one build.
Now you know how to build and experiment with your own images take a look at some examples on Docker Hub and Git Hub to see just what can be accomplished within a docker container.
RUN command in effect opens up a new bash shell in your image at root level i.e. / so if you want to issue consecutive commands in the same directory either
- specify the directory implicitly in each
- chain commands using the operating systems method e.g. && for Debian with a \ character to show new lines
- specify a
WORKDIRfor the remaining commands