A brief Introduction To Docker

Photo by Ian Taylor on Unsplash

A brief Introduction To Docker

Earlier, if companies wanted to run multiple applications on a server, that was impossible. Each server could only handle one application, and any more apps required new physical servers to be created.

Problems with creating Physical Servers one after the other?

  1. Resource Utilization: Running applications on dedicated physical servers meant that each server had to be provisioned for a specific workload. This often resulted in underutilization of server resources because the workload might not require the full capacity of the server at all times. Consequently, organizations had to invest in numerous physical servers to accommodate their applications, leading to higher costs and inefficiencies.

  2. Scalability: Scaling an application meant adding more physical servers to the infrastructure. This process was time-consuming and required careful planning, as it involved procuring new servers, installing and configuring them, and integrating them into the existing infrastructure. Scaling vertically by upgrading the existing servers also had limitations in terms of capacity and cost-effectiveness.

  3. Application Isolation: Running applications directly on physical servers posed challenges in terms of isolating applications from each other. Applications could potentially interfere with one another, causing performance issues or security vulnerabilities. It was difficult to ensure that applications did not impact each other's resources or stability.

  4. Hardware Maintenance and Management: Managing a large number of physical servers required substantial effort. Hardware failures, upgrades, and replacements were labor-intensive tasks that involved physically interacting with the servers. It also meant that hardware maintenance activities could lead to downtime for applications running on those servers.

This problem was first solved by VMs (Virtual Machines).

VMs are just physical emulations of computers that allowed us to run multiple applications on a physical server.

But the problem with VMs?

  1. Each VM needed its own dedicated operating system installation, which meant that it needed its own dedicated memory and CPU resources for that OS, which can lead to performance being impacted.

  2. Due to the above, starting and booting a VM can be slow as each VM needs to boot its own OS. The process can take longer depending on the size of the OS.

Now another recent problem that got solved by Docker:

  • When you let's say locally created a web application/website, and you send the source code to your friend who sets it up locally, it may/may not have not worked for them. But why is there a chance that it wouldn't when it does on your system? Could be because certain dependencies you used would have different versions working on their system, some packages may have been deprecated on their systems or something of this sort. The same issue with trying to setup open source projects locally - The dependencies may have deprecated or may work on a different version on your system, which is a problem Docker solved. How? We shall get into that in a bit.

Another way of looking at the problem of not being able to run 2 applications on 1 server is that when you set up 2 servers using for example: express js, you cant set up both servers to run on a single port, and NEED a separate server to run both the applications.

The problem where to run every new application, we would have to install a new OS or even earlier have a dedicated physical server for it, people started looking for a way to run multiple applications on the same operating system instead of having different OS or Servers for it, which is what got solved by Containers.

From the diagram below, let’s say someone wants to transport a piano, a car and some other big items from India to the US. If you would want to transport each of those items, each of those would get transported in a different manner. However, what a container could do is allow you to put all of the items to be transported in it, and then you just transport the container which has everything in it.

Following this analogy, if you transported a web application using a container, where everything related to the web app (Dependencies, Database, Source Code), etc gets transported using a container, the friend you’d send the container to would be able to then use that app locally regardless of the version of dependencies, something being deprecated etc.

In Virtual Machines, everything happens on just one device, however, each app is divided and given its own OS and other systemic requirements that come with needing its own OS, just that all of the division into different OS for different apps is virtual and not physical.

In a Container, you have just one OS, and on top of that, you have a Container Engine, over which you can run multiple apps.

So long story short, what containers allow you to do is run/deploy/scale etc your applications in an Isolated Environment, where you, unlike virtual machines, don’t need to install a new OS for each new Application. And, what Docker allows you to do is Create, Manage, Scale etc containers to run several applications.

Docker consists of a few things from its architecture to know about:

Docker Runtime:

Runtime essentially allows us to start and stop the containers running.

Two types:

  • RunC - works with the Operating System and starts and stops containers.

  • ContainerD - lies on the higher level of the hierarchy. Manages RunC. Also helps the container to interact with the network (Internet), how to get data from the Internet (also known as pulling images) - (Ignore what Images mean, we’ll come to that in a bit).

Every Container has a RunC and ContainerD.

Docker Engine, Daemon:

Docker Daemon is essentially like a personal assistant, which also has a server component, which has some REST APIs, which allow users to manage containers (Delete, Create, etc). And the Docker Engine is like the brain behind Docker Daemon. It is the main part of Docker that manages everything. It's responsible for coordinating the Docker containers and making sure they all work together nicely.

The communication to perform operations on Docker Containers is done using the Docker CLI.

Q) How does the flow of making an operation happen work?

You, using the Docker CLI make an API call to the daemon, whose server component coordinates with Docker Runtime to make the operation happen.

Q) What is Orchestration Engine?

An Orchestration Engine in simple words allows us to manage containers.

Here, let’s assume the above is Docker setup on a system that is running several containers, each of which contains Version 1 of an application. Now, you want each of these to shift to running Version 2 of an application. To manually do it on a large scale is tedious, hence orchestrational engines like Kubernetes (which is one of the features it has) are used to do so.

Docker has its own built-in Orchestrational Engine, but people end up using the most common one - Kubernetes.

Let’s hypothetically say you make some food, and you really really like it. Let’s say you have a friend who lives 8000 miles away from you. Now, from the previous analogy where we put things in a container and send it, we would make the dish and send the created dish in the container 8000 miles away. Doesn’t make sense right? In such a scenario, the ideal situation would be to send the complete recipe, and the person 8000 miles away makes it themselves using all the information given in the recipe.

Let’s similarly say you have an app, you wouldn't really send the running application to your friend just like sending a cooked dish right? You’d essentially just send the recipe (in our case all instructions, the source code, the DB, etc), and the person just needs to do XYZ and then use the app like I am. And this entire set of instructions which includes all the source code, DB, etc is what we call the Docker Image.

Essentially, I just need to create an Image of my application, and the person 8000 miles away can just run that image and then use the app.

Docker Images are created using Docker Files. The Docker file essentially consists of the List Of Instructions that would be used to run the application for someone else.

If an application needs to be containerized, a Docker File is written for it, which then gets converted to a Docker Image and the Container is essentially just a running Instance of an Image.

OCI: (Open Container Initiative)

OCI started a Runtime spec and an Image spec, which was basically a set of rules everyone agreed to follow regardless of Docker or any other container tool being used.

  1. Runtime Specification: The Runtime Specification defined how a container should be executed or run. It specifies the rules and requirements for launching and managing containers on a computer. It includes details such as how the container's file system should be structured, how processes should be isolated within the container, and how the container interacts with the host operating system. Essentially, the Runtime Specification ensures that containers created by different container runtimes can work consistently and reliably across various systems.

  2. Image Specification: The Image Specification defined the format and structure of a container image. A container image is a package that contains all the necessary files, libraries, and dependencies required to run a specific program or application within a container. The Image Specification describes how the image should be built, organized, and distributed. It ensures that container images are portable and can be shared and used by different container runtimes that adhere to the OCI standards.

Overall, OCI defines the standards for how Docker files, Docker images, and Docker containers should work. It ensures that containers created by Docker can be understood and used by other container runtime systems that follow the OCI standards.

Think of the OCI as a rulebook that everyone agreed to follow, so that no matter which container tool you use, the containers can work smoothly on different computers. Docker is one of the popular tools that follows the OCI standards, making it easier for developers to create, share, and run programs using containers.