Understanding Containerization and its implementation by Docker

Reading Time: 4 minutes

Containerization is a famous practice that is being implemented in most of the application. Industries are moving to deploy the application in form of containers rather than with the traditional on-premise method. In this blog, we’ll understand the benefits that containerization provides to Developers as well as DevOps. Let’s begin with the journey

What is Containerization?

This is one of the most popular concepts being followed in the IT sector for the past few years. After introducing Docker, a containerization platform, the containers have evolved to a larger ecosystem. Let’s understand the reason behind their popularity.

In general, a container is a collection of software unified by a namespace, which has the access to operating system kernel, which is shared among multiple containers. The container runs in an isolated environment and has no/very little access between them. Docker adds to this definition by saying that a container is a runtime instance of a Docker image. A running docker container has 3 things included:

  • A Docker image
  • An execution environment
  • A standard set of instructions

If you are from an Object-Oriented world, you can use the analogy of classes and objects to understand this topic. Docker images are like classes, where containers are the running instance of those images, just like objects.

Docker Ecosystem

A Docker Ecosystem mainly consist of 3 components

  1. Docker Engine:
    The Docker engine provides the runtime environment to the containers. This also acts as the packaging tools which helps in building the docker images.
    It must be installed over the host operating system where the images are actually going to be executed.
  2. Docker Hub:
    It is an online cloud service provided by docker which acts as a repository for storing Docker Images which can be shared among multiple users.
  3. Docker CLI:
    This component is responsible for making the API calls to the Docker Engine. These calls are used to manage the container lifecycle over the Docker Engine.

Benefits of Containerization

To Developers

  1. The main benefit a developer would get is a standard for developing and packaging an application.
    For eg: For a java developer, a jar (artifact for java application) would require the same version of java to run, with which it was build.
  2. Testing an application and verifying its dependency with other application modules would be as easy as running a simple docker run <dependent-container-image>
  3. Developers get an easy support for new Microservice architecture.
  4. Another major benefit is that it alleviates the platform compatibility issues.

To DevOps

  1. Using containers simplify release management.
  2. The deployments are much more reliable and speedy, which ultimately helps in frequent releases.
  3. Application lifecycle is simplified as now application is configured ones and ran multiple times (scaling up the replicas of container)
  4. Environments consistency (Dev, QA and Prod) can be easily achieved.

Containers: A common language between Dev and Ops

In a containerized environment, If any issues come up in any of the environments (especially production) the issues can be debugged easily at the container level and then communicated to the Dev team for a (quick) fix.

The Dev team will also be easily able to replicate the problem since the container will run in an isolated environment every time and this eliminates the runtime issues or host compatibility problems.

Container Lifecycle in Docker

Talking about the container lifecycle, we’ll see how a container is born and then went to a deletion state. The foremost requirement for creating a container is a Docker Image.

A Docker Image is a template that gets instantiated to get a running container. Docker Image can be available to us in 2 ways. Either we can get it from Docker Hub, an image repository, or build our own images using Dockerfile.

Dockerfile is a file where we mention all the packages and dependencies that need to be present for running our application. This is the concept which actually makes the container independent as everything is made available within the container and it doesn’t have to share anything with the host OS. I’ll create a separate blog post to include the steps and best practices for writing a Dockerfile.

Now after we have the Docker Image, we can simply run that image to get a Docker Container out of it. That container is actually the running instance of our application.

A Quick Hands On

Prerequisites:

  1. Docker Installation: If you don’t have docker installed on your system, follow this documentation. It’s pretty much straight forward.
    Note: After completing the installation, follow the Post-Installation steps which will be applied only after a reboot. This will help you in running docker-cli without sudo permissions.
  2. DockerHub Account: Make sure you have an account over DockerHub, If not, sign-up here.

Quickstart Gist

## Check docker server and client version
docker version
## Check for running containers | Currently, it should be empty
docker ps
## Check for images | Currently, it should be empty
docker images
## Now Pull an Image (Nginx) from DockerHub
## SYNTAX: docker pull <image-name>
docker pull nginx
## Check for the image again
docker images
## Run the image to get the container
## FYI, nginx is a webserver use to host webpages
## SYNTAX: docker run [OPTIONS…] <image-name>
docker run –name my-nginx -d nginx
## –name: To give a name to the container
## -d: Run the container in background (datach mode)
## Verify if container is running
docker ps
## Get logs for the container
## SYNTAX: docker logs <container-name/id>
docker logs my-nginx
## Executing a command within the container | Checking the default nginx configuration
## SYNTAX: docker exec <container-name/id> <cmd-to-be-executed>
docker exec my-nginx cat /etc/nginx/conf.d/default.conf
## Get various container information
## SYNTAX: docker inspect <container-name/id>
docker inspect my-nginx
## Get the default webpage of nginx container
## Find the container IP and open it over browser
docker inspect my-nginx -f '{{ range.NetworkSettings.Networks }}{{ .IPAddress }}{{ end }}'
## -f: Used to define the Format in which we want (get value against particular key)
## Let's try to stop the running container
## SYNTAX: docker stop <container-name/id>
docker stop my-nginx
## Check if container has stopped
docker ps -a
## -a: Show all containers (Running and Stopped)
## Start the container again
## SYNTAX: docker start <container-name/id>
docker start my-nginx
## Verify if container has started
docker ps
## Show only Running containers
## Edit the default webpage of Nginx to some HTML page of our own by modifying the container
## Create your own webpage using Heredoc syntax
cat > index.html << EOF
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
<body style="background-color:powderblue;">
<center>
<h1>This is Docker Quickstart</h1>
<h3>This tutorial is provided by <h2>Yatharth | DevOps Engineer at Knoldus</h2></h3>
<p> <b>Like and share</b> the blog if you found it helpful </p>
<p> For more blogs from this Author, <a href="https://blog.knoldus.com/author/yatharth45/&quot; target="_blank" >Click here</a></p>
</center>
</body>
</html>
EOF
## Copy the html file from local to the container
## SYNTAX: docker cp </path/to/file> <container-name/id>:</dest/path/to/file>
docker cp index.html my-nginx:/usr/share/nginx/html/index.html
## Verify if nginx started rendering the updated html page | Get the container IP again and copy in the browser
docker inspect my-nginx -f '{{ range.NetworkSettings.Networks }}{{ .IPAddress }}{{ end }}'
## Now save the updated container with a new image
## Why?? | Since containers are ephemeral, the changes we have made will be lost once the container is stopped.
## SYNTAx: docker commit <container-name/id> <new-image-tag>
docker commit my-nginx my-nginx-image
## Check the new image
docker images
## Run the new container image
docker run –name my-new-nginx -d my-nginx-image
## Verify that the container is running
docker ps
## Check the webpage hosted by the new nginx container | Get the IP address of the container and copy it over browser.
docker inspect my-new-nginx -f '{{ range.NetworkSettings.Networks }}{{ .IPAddress }}{{ end }}'
## Rename the existing docker image to "<dockerhub-id>/<image-name>"
## WHY?? Because, for pushing the image to dockerhub, we need to follow the above format
## SYNTAX: docker tag <image-name> <dockerhub-id>/<new-image-name>
docker tag my-nginx-image yatharth0045/my-nginx-image
## Login to dockerhub via docker CLI using your dockerhub creds
docker login
## It will prompt for your ID and Password
## Push the image to dockerhub
## SYNTAX: docker push <dockerhub-id>/<image-name>
docker push yatharth0045/my-nginx-image
## Remove the running container
## Way 1 | Stop the container and then remove it
docker stop my-nginx && docker rm my-nginx
## Way 2 | Forcefully remove the container
docker rm -f my-new-nginx
## Delete the image from local
## Removing multiple images
## SYNTAX: docker rmi <image/s>
docker rmi nginx my-nginx-image yatharth0045/my-nginx-image
view raw docker-quickstart.sh hosted with ❤ by GitHub

Conclusion

After reading this blog, you’ll now be with what containerization is and what are benefits the teams are getting at building as well as deploying the application as containers. Also, with the quick start I’ve provided, you will have a hands-on over most of the docker commands, and after a little practice, these commands will be very handy for you.
Still, if you have any doubts/suggestions, you can contact me directly at yatharth.sharma@knoldus.com

Also, I would like to thank you for sticking to the end. If you like this blog, please do show your appreciation by giving thumbs-ups and share this blog and provide suggestions on how can I improve my future posts to suit your needs. Follow me to get updates on different technologies.