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:
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.
Create a Dockerfile – most crucial step
Build your image – using docker build
Run your image locally – using docker run
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:
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.
Technorati Tags: Docker,DevOps,Cloud,Azure,Virtualization,Containers