When interviewing or interviewing others in the past, a frequently asked question is: how do you understand the container according to your resume that you are familiar with container technology? A fairly good answer is: the container technology itself is not a new technology. The container is essentially a special process on the host operating system. The Namespace and Cgroup technologies are used to realize the isolation and restriction of resources, realize the container image, and solve the problem of application distribution. So far, it can be said that the understanding of containers is quite comprehensive.
Docker installation: I didn't want to write about a lot of things that need to be searched online and don't need to understand, but I read a lot of articles about the installation process. It's a little pit, so I'd better write about it. The installation process is operated on ubuntu, because CentOS7 will not be maintained in the future. I heard that ebay production environment systems also use ubuntu.
step1: update Ubuntu apt get source
sudo apt-get update sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release
Step 2: add Docker official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
step3: address of the warehouse where Docker stable version is installed
echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
step4: installing Docker
sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io
It usually runs automatically after installing Docker, but many people want to use this Docker as a test or staging environment for a long time, so it is estimated that there will be problems directly. The default storage directory of Docker is / var/lib/docker /. The disk of some hosts is very small, especially the virtual machine. It takes a period of time to fill up the system disk and has to be moved away, which is very troublesome. It's better to do it in one step, Put the data storage directory on a larger disk, such as / data/docker /.
step5: edit the / lib/systemd/system/docker.service file and add -- data root = / data / docker after the ExecStart option to customize the data directory. The results are as follows:
ExecStart=/usr/bin/dockerd -H fd:// --data-root=/data/docker --containerd=/run/containerd/containerd.sock --log-level warn --log-opt max-size=100m --log-opt max-file=5
Then reload systemd and restart the Docker process.
systemctl daemon-reload systemctl restart docker
step6: verify that the container has been installed successfully
# docker run hello-world Hello from Docker! This message shows that your installation appears to be working correctly.
Using Docker to run an Nginx container: Docker is used as a tool. In fact, there is nothing complicated. As long as you master Dockerfile, you can use some basic commands. Next, based on Nginx, make our image and run it.
Step 1: write Dockerfile
# Specify your basic image here. It is recommended to write a fixed version number, otherwise the default latest update may lead to incompatibility of your code FROM nginx:1.21.3 # Default directory after entering the container WORKDIR /usr/share/nginx/html # Change the index.html content to what we want RUN echo "This is my first image base nginx!" > index.html
Step 2: generate Docker image
docker build -t my_nginx:v1.0 -f Dockerfile .
step3: view the generated image and use it to start the container
# docker images my_nginx v1.0 5d0547b2cc8d 3 hours ago 133MB # docker run -d 5d0547b2cc8d # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 6961dd4fce83 5d0547b2cc8d "/docker-entrypoint...." 18 minutes ago Up 18 minutes 80/tcp strange_jepsen
step4: check the container IP address and use the container IP to access the nginx service. Here we introduce the use of the nsenter command. The scenario is that there is no ifconfig command in our nginx image, but we want to check the IP address. At this time, we can enter the Namespace of the container through the nsenter command and adjust the container with the command on the host.
[root@iZ2zec5wzaupsrdu55oeaiZ docker]# docker inspect 6961dd4fce83 | grep -i pid "Pid": 30176, "PidMode": "", "PidsLimit": null, [root@iZ2zec5wzaupsrdu55oeaiZ docker]# nsenter -t 30176 -n ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.18.0.2 netmask 255.255.0.0 broadcast 172.18.255.255 ether 02:42:ac:12:00:02 txqueuelen 0 (Ethernet) RX packets 18 bytes 1256 (1.2 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 14 bytes 1386 (1.3 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@iZ2zec5wzaupsrdu55oeaiZ docker]# curl 172.18.0.2 This is my first image base nginx!
Turn to the topic and elaborate on Namespace: Namespace is not a new technology. It is a function of the kernel. Docker can realize resource isolation by calling the Namespace function of the kernel. This function isolates kernel resources, so that container processes can run in a separate Namespace, and can only access the resources of the current container Namespace.
There are many resource types under Linux, so Namespace is divided into the following categories to limit resources:
- PID namespace: used to isolate the process ID.
- Network namespace: isolate the network interface. In the virtual net namespace, users can have their own independent IP, route, port, etc.
- Mount namespace: file system mount point isolation.
- IPC namespace: isolation of semaphores, message queues, and shared memory.
- UTS namespace: isolation of host name and domain name.
- User namespace: isolation of users and groups.
The isolation of various resources is listed above. Let's take PID namespace as an example to see how it is implemented in the Linux operating system. The system call to create a process in the Linux system is clone(), as shown in the following code:
int pid = clone(main_function, stack_size, SIGCHLD, NULL);
But once we pass in clone_ According to the newpid parameter, the newly created process enters an independent space. In this space, its own PID is 1. From the outside, it is a normal process. The process number may be xxx, but certainly not 1, because process 1 is the systemd process of the operating system. The following code realizes process isolation:
int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);
Generally speaking, after a process is started, Namespace will give it a package, and then the process will play freely in its own small world. However, Qi Tian Da Sheng is unable to escape the five finger mountain of the Tathagata. For developers, it is still a process on the operating system.
For most people, we only need to know how Docker implements process isolation. If we need to dig deeper in the future, we can look for it according to the Namespace function of the operating system.