Tuesday, March 31, 2015

The Container World | Part 7 Building your own Docker Images

In the previous post I gave an overview of Docker and explained what it takes to run a simple container. In this post I will be demonstrating Docker images which provides the basis for running containers. I will go into a bit more detail about what exactly a Docker image is, how to manage your images and also demonstrate how to build an image from scratch and have it store locally on your host.

What is a Docker image?

For those of us with familiarity in the virtualization space this might come a bit easier of a concept. A Docker image can be thought of as a template or as source code for all your containers. Docker images provide the building blocks of containers and allow us to define characteristics of containers such as the OS, application and processes running inside the container. Images are what you use to build and launch your containers and is what makes Docker so lightweight and portable. Docker images are what we store in registries that provide us with a git-like functionality of sharing, updating, deploying and storing. There are a few ways of creating images such as by pulling already created images from a repo, creating them from a container or from Dockerfiles.

Managing your Docker images

After learning a bit more about images its easy to see how important it is to manage your images. Docker uses public and private registries to help us easily manage our images. We will just be using the local repo on our host for simplicity reasons of this post.

Search for an image:
    # sudo docker search <image_name>
    # sudo docker search centos

Pull down an image locally from repo:
    # sudo docker pull <image_name>
    # sudo docker pull centos

Push an image to the repo:
    # sudo docker push <image_name>
    # sudo docker push centos

Remove an image:
    # sudo docker rmi <image_name>
    # sudo docker rmi centos

Building a Docker image

This post will demonstrate how to create a custom base image for nginx that you can use to create and run new containers from. This is a way of ensuring that your containers are being created the same and customized to fit your environment and liking. There are a couple of ways doing this. My preferred method is to use Dockerfiles (which will cover in the next tutorial) but for this demo I will be using a custom script written from the Docker Github page (Thanks all you lovely people at Docker!) to build a base image.  Another way of course would be to use the "docker pull" command above. Ill demonstrate how to pull down a Centos image, customize it, and then use it to deploy my containers from. Ill be demonstrating using a Centos 6 host and creating a Centos 6 image for running nginx.

1. Go to the Docker Github page and grab the mkimage-yum.sh file . Please be sure to check out the other scripts Docker has provided for other Host OS and other image distributions.

# wget -O ~/mkimage-yum.sh https://raw.githubusercontent.com/docker/docker/master/contrib/mkimage-yum.sh
--2015-03-31 14:30:03--  https://raw.githubusercontent.com/docker/docker/master/contrib/mkimage-yum.sh
Resolving raw.githubusercontent.com...
Connecting to raw.githubusercontent.com||:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2708 (2.6K) [text/plain]
Saving to: “/root/mkimage-yum.sh”

100%[===================================================================>] 2,708       --.-K/s   in 0s

2015-03-31 14:30:03 (229 MB/s) - “/root/mkimage-yum.sh” saved [2708/2708]

Please note that the mkimage-yum.sh script will actually automatically run a container from the image as well. If you don’t want this just comment out line 106 in the script above:

#docker run -i -t $name:$version echo success

 2. Run the script like below. It will take a minute or two to complete.
# ./mkimage-yum.sh <desire_name_of_image>
# ./mkimage-yum.sh centos6-new

# validate new image is created and imported
# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos6-new         6.6                 61faa3d658e3        22 seconds ago      237.5 MB

3. Once it completes we can create a container from that newly created image. We will be attaching to the container, running the customization stuff and then committing the container into an image that we can use later.
    # docker run -it --name centos6-nginx centos6-new:6.6 /bin/bash

4. The above command will attach you to the running container. So just treat this as you would to install and configure nginx on a normal linux server. I used the following steps to complete customizing my nginx environment.  NOTE: This is where you would be customizing to fit your environment. GO NUTZ!
[root@dba3856e6c99 ~]# ###created the following directories
[root@dba3856e6c99 ~]# mkdir -p /var/www/website/public_html /var/www/website/log /etc/nginx/sites-available
[root@dba3856e6c99 ~]# ###install nginx
[root@dba3856e6c99 ~]# yum install -y nginx
[root@dba3856e6c99 ~]# ###add the following line to nginx.cong file
[root@dba3856e6c99 ~]# vi /etc/nginx/nginx.conf
[root@dba3856e6c99 ~]# tail -2 /etc/nginx/nginx.conf
    include /etc/nginx/sites-available/*;
[root@dba3856e6c99 ~]# ###create the virtual host for the website and paste the following text
[root@dba3856e6c99 ~]# vi /etc/nginx/sites-available/website
[root@dba3856e6c99 ~]# cat /etc/nginx/sites-available/website
server {
    server_name website;
    access_log /var/www/website/log/access.log;
    error_log /var/www/website/log/error.log;
    root /var/www/website/public_html;

    location / {
        index index.php;

    # Disable favicon.ico logging
    location = /favicon.ico {
        log_not_found off;
        access_log off;

    # Allow robots and disable logging
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
[root@dba3856e6c99 ~]# ###start and chkconfig the nginx service
[root@dba3856e6c99 ~]# service nginx status
nginx is stopped
[root@dba3856e6c99 /]# echo "service nginx start" >> ~/.bashrc

5. Logout  of the container and check to make sure its exited and no longer running.
# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
dba3856e6c99        centos6-new:6.6     "/bin/bash"         21 minutes ago      Exited (0) 2 seconds ago                       centos6-nginx

6. Now we can "commit" that container into an image. We will then be able to use that image to create all of our "new nginx" servers.
# docker commit <container_id> <repo>/<image_name>:<tag> ###NOTE: you can also use -m to document the image and -a to document the author
# docker commit dba3856e6c99 centos6/nginx:6.6
# docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
centos6/nginx       6.6                 d88af477ead3        8 seconds ago       407.3 MB

centos6-new         6.6                 61faa3d658e3        About an hour ago   237.5 MB

7. To test out the new image, lets run a new container from the image on port 8080 of the host and see if we get a valid website.
# docker run -it -d --name <new-container-name> -p 8080:80 <repo>/<image_name>:<tag> <some_command> ### -d runs in daemon mode (non attached)
# docker run -it -d --name new-nginx -p 8080:80 centos6/nginx:6.6 /bin/bash

Go the host IP address on port 8080 in our web browser to validate you get a screen that looks like the one below.

If you can see it then you have made it!

Hopefully this has given a good overview of Docker images as it is one of the most important aspects of Docker. In the next tutorial Ill demonstrate how to create an image but using a Dockerfile which is my preferred method.

No comments:

Post a Comment