Understanding Docker

Prakhar Agarwal
10 min readFeb 21, 2021

Before telling about docker , let’s take a scenario which will help you in understanding where exactly docker comes into picture. So let’s say you worked on a MEAN stack application and any of your friend/colleague asked you to show your running application but unfortunately you are not carrying your laptop with you and the only option left with you is to use there laptop. Now , to run application on a new system, first you would be needing all prerequisites software or dependencies that supports your application then pull code from GIT and do lot other stuffs to make it up and running. This is where docker comes handy . So with docker you can just create an image that will have your application and all related dependencies. You just push the image to docker hub ( cloud docker repo) and then you can simply pull it to any other system with docker installed on it and run your application without thinking much about other software dependencies.

What is Docker ?

Docker is a containerisation platform which packages your application and all of its dependencies together in the form of containers and also it ensures that your application works seamlessly in any of the other env like DEV/QA/PROD
irrespective of the software or other platform dependencies , it just requires docker installed on other env that's it. Simple Right ?

Docker is basically its own isolated environment packaged with all needed configuration.

Unlike VM docker doesn't have its own OS therefore it saves a lot memory and also reduces overburden on your system whereas a virtual machine will include a complete operating system. It will work independently and act like a computer.

  • Docker shares same host OS Kernel for the hardware management.
  • Containers are lightweight and can easily be shared via docker hub.
  • As it sits on the HOST OS and doesn’t have its own OS , it occupies less RAM than VMs.

From Docker’s official website

Docker is written in the Go programming language and takes advantage of several features of the Linux kernel to deliver its functionality. Docker uses a technology called namespaces to provide the isolated workspace called the container. When you run a container, Docker creates a set of namespaces for that container.

How Docker works ?

Docker works on a client-server architecture. They both connects using docker REST Api. All these component together can also be called as Docker Engine.Docker client send requests to docker server through docker REST api.

  1. Docker Daemon: A persistent background process that manages Docker images, containers, networks, and storage volumes. The Docker daemon constantly listens for Docker API requests and processes them.
  2. Docker Engine REST API: An API is used by applications to interact with the Docker daemon. It can be accessed by an HTTP client.
  3. Docker CLI: A command-line interface client for interacting with the Docker daemon. It significantly simplifies how you manage container instances and is one of the key reasons why developers love using Docker.

What is Docker-Machine ?

Docker Machine was the only way to run Docker on Mac or Windows prior to Docker v1.12. Initially docker works natively with linux and to run it with windows/mac we should install docker-machine which is nothing but a lightweight linux VM.

Docker Machine is a tool that lets you install Docker Engine on virtual hosts, and manage the hosts with docker-machine commands. You can use Machine to create Docker hosts on your local Mac or Windows box, on your company network, in your data center, or on cloud providers like Azure, AWS, or DigitalOcean.

It is not recommended to use this now as we have got Docker Desktop for Mac and Docker Desktop for Windows are available as native apps.

How Docker Containers are made and run ?

Docker containers are made from docker images and Docker File is used to build docker images .

DockerFile

DockerFiles are plain text file which describes step-by-step instructions of all the commands you need to run to assemble a Docker Image.

DockerImage

Docker Image contains all your project related things ( code , libraries , dependencies etc ). Run this docker image to get a running instance of docker container. You can spin n number of containers with this image. You can even push this docker image to docker hub and share it with other teams. This will also make sure it will run in the exact same way as it was running on your system. Due to their read-only quality, these images are sometimes referred to as snapshots.Since images are in a way just templates which would be used as a base to build a container. A container is, ultimately, just a running image. Once you create a container, it adds a writable layer on top of the immutable image, meaning you can now modify it.

DockerContainer

A Docker container is a virtualized run-time environment where users can isolate applications from the underlying system. These containers are compact, portable units in which you can start up an application quickly and easily.

Hands On Time

We are done with the theory part. Now let's get our hands dirty and move on to the hands on part in a step wise instructions. By the end of this section you will have basic understanding to start with dockerfile , creating images from this file and running container.

Firstly make sure you have docker installed on your system. If not please visit this official link and follow the step wise instructions to install docker desktop for your os.

Once installed open command prompt or terminal ( for mac ) and execute this command and check the output

$ docker container run hello-world  Unable to find image 'hello-world:latest' locally
latest: pulling from library/hello-world
1b930d010525: Pull complete
Status: Downloaded newer image for hello world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker did the following :
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the “hello-world” image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal.
To try something more ambitious, you can run an ubutu container with:
$ docker run -it ubuntu bash

Let look at what's happening behind the scene

  • here docker engine tried to find an image named hello-world.
  • But as its just a start and our first container run, there is no such image stored locally
Unable to find image 'hello-world:latest' locally
  • Docker engine goes to DockerHub(docker cloud repo), looking for hello-world image.

https://hub.docker.com/

  • It finds the image, pulls it down and then runs it in a container.
  • Hello World only function is to output the text you see in the terminal, after which the container exits

But what if you got a set of instructions to perform on the base image like installing dependencies or exposing port or anything. Here, come dockerfile.

Lets see how that works in sequence of steps:

  1. Create DockerFile :

Docker file can be created with any name. In Build your Docker File using the following instructions.

#This is a sample Image
FROM ubuntu
RUN apt-get update
RUN apt-get -y install nginx
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

In this docker file we are providing instruction to create an image with ubuntu as base image with nginx installed on it.

The following points need to be noted about the above file −

  • The first line “#This is a sample Image” is a comment. You can add comments to the Docker File with the help of the # command
  • The next line has to start with the FROM keyword. It tells docker, from which base image you want to base your image from. In our example, we are creating an image from the ubuntu image. The image will be pulled from docker hub repository.
  • The next command is the person who is going to maintain this image. Here you specify the MAINTAINER keyword and just mention the email ID.
  • The RUN command is used to run instructions against the image. In our case, we first update our Ubuntu system and then install the nginx server on our ubuntu image.
  • In last command Nginx uses the daemon off directive to run in the foreground.

Every command you specify (FROM, RUN, COPY, etc.) in your Dockerfile causes the previous image to change, thus creating a new layer.

The concept of layers comes in handy at the time of building images. Because layers are intermediate images, if you make a change to your Dockerfile, docker will build only the layer that was changed and the ones after that. This is called layer caching.

2. Build Image :

It's time to build the image from the created docker file. Syntax of command to build docker image:

docker build -f <docker-file name> -t <image-name>:<tag> <dir>
  • -f <docker-file name> : In case the name is dockerfile you can skip this argument and if anything else then you need to provide the name of the file.
  • -t <image-name>:<tag> To tag this image with image-name and <tag> is nothing but a version.
  • <dir> : path where dockerfile is located. For current directory just add . (period)

Command to run :

docker build -t ubuntu-nginx-test:latest .

Note : If you run this same docker file again you will notice that it got build pretty quick as compared to previous run that’s because everything gets picked from cache as you already ran the same step and it was cached at that time. To confirm this do docker image ps after second run and you will find both the images will have same image id.

3. Run Container :

Now let's spin a container using the image that we just created. Command syntax

docker run -d -p <host-port>:<container-port> --name <container-name> <image-name>:<tag>

  • -d : This option is used to run the container in detached mode. This is so that the container can run in the background.
  • -p : it is used for port mapping i.e. host machine port with the container port.

Command to run container for above created image

docker run -d -p 1234:80 --name ubuntu-nginx-container ubuntu-nginx-test:latest

Here, we are porting nginx default 80 port with our machine’s 1234 port ( it could be anything except the one that are already in use).

4. Verify Results

Goto any of the browser and hit http://localhost:1234 and you should see default nginx page.

5. Docker Hub

If you have reached here it means you are able to see the nginx page and tada!! you have successfully spin you first docker container. Now this one is a basic and simple nginx container with ubuntu as a base image but just imagine in case this would be an entire application. How easy it would be for you if you could push this image to a public repository on the cloud then simply pull the same to any other system and make it up and running.Most of the images such as Centos, Ubuntu, and Jenkins are all publicly available for all. So let's push our image to public repo.

5a) Log into Docker Hub and create your repository. This is the repository where your image will be stored. Go to https://hub.docker.com/ and log in with your credentials or else sign up .

5b) Click “Create Repository” on the screen and create a repository with the name demorep. Make sure that the visibility of the repository is public.

5c) Once the repository is created, make a note of the pull command which is attached to the repository.

5d) login into the Docker Hub repository from the command prompt. The Docker login command will prompt you for the username and password to the Docker Hub repository.

5e) We need to tag our ubuntu-nginx-test to the new repository created in Docker Hub. We can do this via the Docker tag command.

docker tag imageID <username>/<repositoryname>:tagname
  • imageID − This is the ImageID which needs to be tagged to the repository.
  • Repositoryname − This is the repository name to which the ImageID needs to be tagged to.

Example

sudo docker tag ab0c1d3744dd demousr/demorep:1.0

5f) Once the image has been tagged, it’s now time to push the image to the Docker Hub repository. We can do this via the Docker push command.

docker push Username/Repositoryname:tagname
  • Repositoryname − This is the repository name which needs to be pushed to the Docker Hub.

Example

docker push demousr/demorep:1.0

If you go back to the Docker Hub page and go to your repository, you will see the tag name in the repository.

Now let’s try to pull the repository we uploaded onto our Docker hub. Let’s first delete the images, ubuntu-nginx-test from the local Docker host. Let’s use the Docker pull command to pull the repository from the Docker Hub.

docker pull UserName/Repositoryname:tagname

Example

docker pull demousr/demorep:1.0NOTE:Everything on docker hub is related to tag name .

Other Useful Commands

  • docker ps it gives all the existing running containers.
  • docker ps -a it gives all the containers including the exited ones.
  • docker restart <container_id> to restart exited container
  • docker image ls list all the images
  • docker stop <container_id or name > to stop the container
  • docker rm <container_id or name > to remove container
  • docker image rm <image_id or name> to remove image
  • docker rm -vf $(docker ps -a -q) kill all containers
  • docker rmi -f $(docker images -a -q) remove all docker images
  • docker logs <container_id or name> get ogs of the provided container
  • docker exec -it <container_name> /bin/bash to get a bash shell in the container.
  • docker exec -it <container_name> <command> to execute whatever command you specify in the container.
  • docker exec -it <container-id> sh to get into shell
  • docker system -df gives the total size of all images , containers.
  • docker image prune removes all images that are not tagged.
  • docker image prune -a removes all unused images.

Thanks for taking out the time and going through this article.

--

--

Prakhar Agarwal

An enthusiastic coder ,learner and a mountain lover.