Abstract:What makes Docker fire is the Docker image. He packaged all of an application’s dependencies, completely solved the problem of environmental consistency, and redefined the way software was delivered, improving productivity.

This article is shared from Huawei Cloud community “Understand container, let’s start with its history”, author: technology torchbearer.

Much has been written about the history, development, and nature of the technology of containers on the Internet. This article aims to explain this technology through a series of articles based on my work experience and understanding.

The history and development of containers

1, the past

Speaking of containers, WE have to mention LXC (Linux Container), which is the former life of Docker, or Docker is the user of LXC. The full LXC capabilities were incorporated into the Linux mainline in 2008, so the container concept was pretty much fixed in 2008, not built by Later Docker. LXC is a container technology provided by the Linux kernel, which provides lightweight virtualization capabilities and can isolate processes and resources. However, in summary, there are only two main knowledge points: Cgroups (Linux Control Group) and Namespace. Figure them out, and you’ll have a good handle on container technology.

  • Cgroups: Focus on limits. You can manage resources by limiting the usage of resources, including CPU, memory, and disk resources.
  • Namespace: Focus on isolation. Isolate the Linux view seen by the process. In plain English, containers do not affect each other, and containers and hosts do not affect each other.

2. Having a tough start as a teenager

In 2009, Cloud Foundry implemented a container operation based on LXC under the project name Warden. In 2010, dotCloud also implemented a container engine, which is now Docker, based on LXC technology and using Go language. DotCloud was a small company at the time, and Docker, from humble beginnings, had a hard time living a relatively unexciting life.

Grow into a Big MAC

In 2013, dotCloud decided to open source Docker. After open source, the project suddenly took off. From a large point of view, the cause of the fire is Docker’s slogan “Build once, Run AnyWhere”. Ha ha, is it deja vu? Write Once, Run AnyWhere. It’s tempting for a programmer to write a program and then package it as an image so it can be deployed and run anywhere, with development, test, and production environments identical. No longer do programmers have to fix all kinds of bad problems caused by different environments.

The phenomenal popularity of Docker’s open source project directly drove dotCloud to change its name to Docker in 2013. Docker also grew rapidly, killing off CoreOS ‘RKT container and Google’s LMCTFY container, and becoming the de facto standard for containers. So later people think of containers as dockers.

To sum up, what makes Docker fire depends on Docker image. He packaged all of an application’s dependencies, completely solved the problem of environmental consistency, and redefined the way software was delivered, improving productivity.

It was eaten by foreign powers

Docker has grown rapidly in the container space, and its ambitions have naturally grown. In 2014, the company launched The container cloud product Swarm (a similar product of K8s) to expand its business. At the same time, Docker has an absolute voice in the open source community and is quite strong. This behavior of going his own way and letting others have no way out made other big players in the container field very unhappy. In order to prevent Docker from being dominant, they decided to fight him.

In June 2015, under the auspices of Google, Redhat, and others, the Linux foundation formed the Open Container Initiative (OCI) to develop an Open industrial standard around Container formats and runtimes, also known as OCI standards. Meanwhile, Docker donated the Libcontainer module to the CNCF community as an implementation of the OCI standard, which is now the RunC project. To put it bluntly, there is now a standard here, where people play together and are not tied to a particular project.

When it comes to Docker, Google’s Kubernetes, the de facto standard for container cloud platforms, is now so widely used that it has become standard at big companies. Kubernetes’ native support for Docker has kept Docker’s market share high. The chart shows the market share of containers at run time in 2019.

But in 2020, Kubernetes suddenly announced that it would remove Dockershim from the trunk when it no longer supports Docker as the default container to run after version 1.20, i.e., after 2021.

As shown in the figure, K8s itself defines a standard Container Runtime Interface (CRI) to interconnect with any Container Runtime that implements the CRI Interface. In the early stage, Docker is the unquestionable king of container runtime. K8s has built-in support for Docker, and realizes the adaptation of standard CRI interface to Docker interface through Dockershim, so as to obtain more users. With the maturity of the open source container runtime Containerd (which implements the CRI interface and is also donated by Docker to CNCF), K8s no longer maintains Dockershim, but is only responsible for maintaining standard CRI, unbinding with a specific container runtime. Of course, K8s does not support Docker, but dockershim who maintain the problem. As K8s’ attitude changes, it’s expected that more and more developers will choose to work directly with the open source Containerd, and what the future holds for Docker and the Docker open source project (now renamed Moby) is anyone’s guess.

At this point, if you’ve noticed, Docker donated Containerd and runC. I don’t know what these two are. Simply put, runC is an implementation of the OCI standard, also known as the OCI runtime, which is really responsible for operating the container. Containerd provides interfaces to manage and control runC. So the picture above, it really should look like this.

Docker is a typical case of a small company becoming popular due to a popular project. It is worth us to learn and understand the story behind it, no matter in terms of technology, company management and how to fight with big factories, no matter in good or bad aspects.

What is a container

According to international practice, when introducing a new concept, we should start with something familiar. Fortunately, the concept of a container is easy to understand. A cup for drinking, a bucket for washing feet, a tank for keeping fish are all containers. In container technology, the “container” is a similar concept, except that it contains something different. Instead, it contains the application itself and the dependencies that the software needs to run. Think of an aquarium as an analogy. The aquarium is a container that contains the application that is the fish, and the container that is the fish food and the water. So you can understand the Docker logo. The ocean is the host, Docker is the whale, and the container on the whale’s back is the container, and our app is inside the container.

When we talk about containers, we can’t get around the container image. Here, we simply think of the container image as a compressed package. The package contains the executable of the application and the files that the application depends on (such as configuration files and dynamic libraries that need to be invoked, etc.). Let’s see what the container actually is.

1. Viewing the container from the host perspective:

1. First, we start the container.

Docker run -d --name="aimar-1-container" eulEROS_ARM: 2.0sp8SPC306 /bin/sh -c "while true; do echo aimar-1-container; sleep 1; done"

This is a standard Docker command. Use the EulEROS_ARM :2.0SP8SPC306 image (image name: version number) to create a new container named “aimar-1- Container “and run the shell command to print “aimar-1-container” every second.

Parameter description: -d: Starts the container in background mode and returns the container ID. –name: Specifies a name for the container.

Docker run -d --name="aimar-1-container" eulEROS_ARM: 2.0sp8SPC306 /bin/sh -c "while true; do echo aimar-1-container; sleep 1; done" 207b7c0cbd811791f7006cd56e17033eb430ec656f05b6cd172c77cf45ad093c

From the output of 207 b7c0cbd811791f7006cd56e17033eb430ec656f05b6cd172c77cf45ad093c we saw a string of characters. It is the container ID that uniquely identifies a container. Of course, you don’t need to use the full ID, just use the abbreviation ID (the first few bits of the full ID). For example, in the following figure, the container ID queried through Docker PS is 207B7C0CBd81

After aiMAR-1 – Container started successfully, we used Ps to check on the host. We can see that the container we just started is a process with PID 12280.

We try to start 2 more containers, and look at the host again, you can see 2 new processes, PID 20049 and 21097 respectively.

So, we can come to a conclusion. From the host’s point of view, the container is the process.

2. Next, we enter the container.

Docker exec -it 207b7c0cbd81 /bin/bash Docker exec is also a standard docker command used to enter a container. Enter the container whose ID is 207b7c0CBd81 and run the /bin/bash command to enable command interaction.

Parameter description:

-it is actually the two parameters -i and -t, meaning that after the container is started, we need to allocate an input/output terminal, so that we can interact with the container and realize the “dialogue” ability with the container.

Change the hostname from kwephispra09909 to 207b7C0CBd81, indicating that we are already inside the container. In the container, we try to start a new process.

[root@207b7c0cbd81 /]# /bin/sh -c "while true; do echo aimar-1-container-embed; sleep 1; done" &

If you go back to the host and take a look at photoshop, you will see that either starting the container directly or starting a new process in the container are both processes from the host’s point of view.

Ii. Container view:

We have entered the container and started the new process. But we didn’t look at the process in the container. When you perform Ps in the container, you will find that the results are completely different from the results when you perform PS on the host. The following figure shows the execution results in the container.

In Container1, you can see only the newly started shell processes (Container1 and container1-embed). You cannot see other processes on the host, nor can you see the processes in Container2 and Container3. These processes seem to be in a box, completely unaware of the outside world, and even think that we run container1 as process 1. (Process 1 is also called init process, and is the ancestor of all other user processes on the system.) So,From the perspective of the container, the container feels “I am the sky, I am the earth, welcome to my world”.

But on the host, they are embarrassingly ordinary processes. Note that for the same process, the process ID seen in the container is not the same as the process ID seen on the host. The process ids in the container are 1 and 1859, and the corresponding process ids on the host are 12280 and 9775 (see figure above).

Third, summary

The above experiment requires the addition of an attribute to the definition of a container.A container is a process => a container is a process separated from the rest of the system. The container is a process running on the host OS (Guest OS is the host OS for a virtual container), and there is isolation between the container and the host, such as process number isolation.

The same process has a different process ID in the container and on the host. For example, Container1 specifies that the PID is 1 in the container and 12280 on the host. So what is the true PID of the process? Of course it’s 12280! Why do you see a PID of 1 in the container? It’s the Linux Namespace that creates this illusion.

The Linux Namespace is the way the Linux kernel uses to isolate resources. Resources in each Namespace are opaque and invisible to other namespaces.

Namespaces are classified by isolated resources:

The PID Namespace is used for the process ID difference between the container and the container mentioned earlier. So where is this Namespace? On Linux everything is a file. Yes, the Namespace is in the file. The Namespace information of a process is recorded in the proc file (/proc/process/ns) on the host. In the following figure, the number (for example, PID :[4026534312]) indicates a Namespace.

For Container1, Container2, and Container3, the PID Namespace is different. The pids in the three containers are isolated from each other. That is, the three containers can have processes with the same PID number at the same time. For example, there are processes with PID=1.

In a namespace, the two processes are visible to each other, but the PID is different from that seen on the host.

At this point, we can refine the definition of the container one more layer. A container is a process separated from the rest of the system = a container is a process separated from the rest of the system using the Linux Namespace implementation.

Click follow to learn about the fresh technologies of Huawei Cloud