Containerize Your Startup: Image Management–Part 3


In the recent past how many times have you heard the buzz around DevOps and Docker? Ever wondered why containerization suddenly gained popularity? I have been wondering this for a while and have finally decided to dig in. In my attempt to educate myself I thought of looking at it through the lens of a startup and trying to figure out how it may be relevant. Stay tuned to this tutorial series to learn more!

Docker: Containerize your startup!
Docker: Containerize your Startup–Part 2

So, here we are in Part 3. In Part 1, I covered how docker may be relevant to startups and how it is being used in DevOps these days. In Part 2, we delved into the functioning of it and saw how easy it is to spin up an environment and do dev-test on it using a docker machine. In todays section we will take it a step forward. We covered how to use existing images on the HUB and how to download and use it, in this post we will explore how to create your own image.

But before we begin, quick recap of the basic concepts:

  • Docker Machine: The Host
  • Docker Engine: The Run Time
  • Docker Container: The Virtualized Platform (think of it as a simulator for your dev-test environment – the most important component )
  • Docker Hub: The Image Repository

The basic commands:

   1: docker run <image>           # Start and Run a container
   2: docker start <name | id>     # Restart a stopped container
   3: docker stop <name | id>      # Stop a Running container
   4: docker rm <name | id>        # Remove or Delete a container
   5: docker ps [ -a ]             # Status of running containers, with -a get details of stopped containers

Lets quickly dive into an example and observe some nuances about a container at a conceptual level:

   1: docker run tutum/hello-world        #Run an image called tutum/hello-world
   2:                                     #tutum/hello-world is a basic webapp which runs on port 80
   3: docker ps -a                        #Process Status of all the docker processes running
   4: CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                  NAMES
   5: 1361ec83de0f        tutum/hello-world   "/bin/sh -c 'php-fpm "   43 seconds ago      Up 42 seconds              80/tcp                 cranky_poitras
   6:  

IMPORTANT: If you scroll to the right to see the full output of the docker process status, you will notice that the webapp is actually running on port 80, hence you would think if you go to the Docker Machine’s port 80, you should be able to see the ‘Hello World’ webapp. But, rethink and this is important: the app is running on the Docker Container’s (the virtualized platform’s) port 80 and not the Docker Machine’s (the host machine’s). We need to map the port 80 of the container to a port on the Docker machine (the host machine). This is done using the following command:

   1: docker run -p 8080:80 tutum/hello-world    # -p maps port 80 of Container to port 8080 of docker machine

With the above command, we have mapped out port 8080 of the Docker machine to the port 80 of the Container. If we point our browser to our Docker Machine’s port 8080, we will be able to see the webapp running:

image

 

   1: adarsha@AzureDocker:~$ docker stop 1361ec83de0f    #Stopping the Container running the webapp
   2: 1361ec83de0f
   3:  
   4: adarsha@AzureDocker:~$ docker rm 1361ec83de0f       # Remove the image from the machine
   5: 1361ec83de0f
   6:  
   7: adarsha@AzureDocker:~$ docker ps -a
   8: CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                  NAMES
   9: 3c4c57831a61        tutum/hello-world   "/bin/sh -c 'php-fpm "   3 hours ago         Up 3 hours                 0.0.0.0:8080->80/tcp   grave_kilby
  10:  
  11: #The above output shows that the process has been removed from the machine, the output above belongs to an older Container which still exists ont he system

So, now we ran an image of tutum/Hello-World in a Container on our Docker Machine: azuredocker-b2233vb0.cloudapp.net. Hopefully, we all are clear about the difference and utility of a container the host machine. Next, let us get into image management and see how we create and upload images in the hub.

Image Management

Till now we have been using images from the public repository of Docker Hub. Now we will upload our own image on the hub for others to use or just simply use the hub as a repository for all our images. Lets go through some important commands first:

   1: adarsha@AzureDocker:~$ docker login        # logs you in to the hub 
   2: Username (adarshadatta):
   3: WARNING: login credentials saved in /home/adarsha/.docker/config.json
   4: Login Succeeded
   5: adarsha@AzureDocker:~$
   6:  
   7: adarsha@AzureDocker:~$ docker images        #List out all images on your Docker machine
   8: REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
   9: redis               latest              9216d5a4eec8        2 weeks ago         109.3 MB
  10: hello-world         latest              af340544ed62        4 weeks ago         960 B
  11: centos              latest              7322fbe74aa5        11 weeks ago        172.2 MB
  12: tutum/hello-world   latest              c833a1892a15        3 months ago        17.33 MB
  13: training/webapp     latest              02a8815912ca        3 months ago        348.8 MB
  14: adarsha@AzureDocker:~$
  15:  
  16:  
  17: #docker build <image_name>        #Build an image from a Dockerfile
  18:  
  19: #docker push <image_name>         #Push an image that you have created on the hib
  20:  

The workflow in image management is pretty simple.

  1. Create a Dockerfile – most crucial step
  2. Build your image – using docker build
  3. Run your image locally – using docker run
  4. Push your image to the hub – using docker push

So let us see this in detail:

1. The DockerFile

This is the most important component. Think of DockerFile being the image creator for your container. Every line you write is like a layer on top of the other. So you could start with a base layer such as an Ubuntu OS or a webserver such as NGINX or any base on top of which you want to create your image. So you always start with FROM <base_layer> and then execute several commands after, each of which acts like an additional layer of you image. A Docker File example:

   1: FROM ubuntu        #This will be the base of your image
   2:  
   3: #From here it can be a series of commands, keep in mind that each build on top of the other
   4: RUN <...>
   5: COPY <....> <....>
   6: CMD <....>

For a full reference and proper guide of how to write the Docker File please refer to the reference or best practices.

Let us see an example of how to write this file. For example, I am building on top of NGINX. Here is what I have got as the Docker File:

   1: FROM nginx
   2: COPY static-html-directory /usr/share/nginx/html

2. Build Image

Now that my Docker File is ready, I can build the image using the ‘docker build’ command. Lets see this in action:

   1: adarsha@AzureDocker:~/dockerimages$ docker build -t adarshadatta/some-content-nginx .
   2: Sending build context to Docker daemon 3.072 kB
   3: Step 0 : FROM nginx
   4: latest: Pulling from library/nginx
   5:  
   6: 2c49f83e0b13: Pull complete
   7: 4a5e6db8c069: Pull complete
   8: 08ecf065655b: Pull complete
   9: ff0618bc0767: Pull complete
  10: 12a77b8bf89a: Pull complete
  11: 5dde53921c3f: Pull complete
  12: a53219dc4d2f: Pull complete
  13: 8c7e9b6e3131: Pull complete
  14: f9bff7d0d06e: Pull complete
  15: 3ac9cfbdf572: Pull complete
  16: 491aec45eaf8: Pull complete
  17: cd3cf76a61ee: Pull complete
  18: Digest: sha256:e2dbdc9824482b79050a67c1e6143365d0eeefcc77bf0e22cc2715d91b8d1ad4
  19: Status: Downloaded newer image for nginx:latest
  20:  ---> cd3cf76a61ee
  21: Step 1 : COPY static-html-directory /usr/share/nginx/html
  22: static-html-directory: no such file or directory
  23: adarsha@AzureDocker:~/dockerimages$ 
  24:  
  25: adarsha@AzureDocker:~/dockerimages$ docker build -t some-content-nginx .
  26: Sending build context to Docker daemon 3.584 kB
  27: Step 0 : FROM nginx
  28:  ---> cd3cf76a61ee
  29: Step 1 : COPY static-html-directory /usr/share/nginx/html
  30:  ---> 7d498b7655a7
  31: Removing intermediate container 3b120ffea164
  32: Successfully built 7d498b7655a7
  33: adarsha@AzureDocker:~/dockerimages$ 

3. Run the Image

Now that my image is built, let us run this image:

   1: adarsha@AzureDocker:~/dockerimages$ docker run -p 80:80 -d adarshadatta/some-content-nginx
   2: 59c2c77b35be3fd4caa55c8860c834e6587592f33a63df1d3b1720991a78399a
   3: adarsha@AzureDocker:~/dockerimages$ docker ps
   4: CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS              PORTS                         NAMES
   5: 59c2c77b35be        some-content-nginx   "nginx -g 'daemon off"   56 seconds ago      Up 55 seconds       0.0.0.0:80->80/tcp, 443/tcp   goofy_wright

4. Push the image on the Docker Hub

Now that our container is successfully running, let us push this image on the HUB using docker push:

   1: adarsha@AzureDocker:~/dockerimages$ docker push adarshadatta/some-content-nginx
   2: The push refers to a repository [docker.io/adarshadatta/some-content-nginx] (len: 1)
   3: 7d498b7655a7: Image successfully pushed
   4: cd3cf76a61ee: Image successfully pushed
   5: 491aec45eaf8: Image already exists
   6: 3ac9cfbdf572: Image already exists
   7: f9bff7d0d06e: Image successfully pushed
   8: 8c7e9b6e3131: Image successfully pushed
   9: a53219dc4d2f: Image successfully pushed
  10: 5dde53921c3f: Image already exists
  11: 12a77b8bf89a: Image successfully pushed
  12: ff0618bc0767: Image successfully pushed
  13: 08ecf065655b: Image already exists
  14: 4a5e6db8c069: Image already exists
  15: 2c49f83e0b13: Image successfully pushed
  16: latest: digest: sha256:79aba3a0f28ce13158f2d2e4207712211c3a040936cd9ae7886fda22dd0ffb44 size: 24497
  17: adarsha@AzureDocker:~/dockerimages$

We can see this successfully pushed on the HUB from the browser:

image

 

That’s it. From now on, you can simply pull this image and reuse this anytime, anywhere on any docker machine as a container using the docker pull command.

Conclusion

In this post, I basically started by reiterating the basics of Docker – the main components and the main concepts through an example. I then proceeded with the basics of image management and how does it function. Please note, the above example is a simplistic depiction of how docker images work and the functionality – basically the work flow. Hopefully, the concepts are clear. Please refer to Getting Started with Images to get a deeper understanding and more examples of how to manage images. If you have any comments or any queries, please reach out to me @AdarshaDatta.


Comments (0)

Skip to main content