Question:
Dear sirs, I have already asked questions about docker several times, and I seem to have learned how to use it – at the level of basic tasks: building and running my applications in containers, dumping volumes into containers (for storing state), the simplest orchestration using docker compose and etc.
Also, I understand the big picture: there are "kernel-level calls". As I understand it, docker server translates any calls from the running container into these "kernel level calls". Thanks to this, I can run centos inside one container on one machine, ubuntu inside another, and alpain inside the third, and it will all work.
Moreover, if I ask for the kernel version with the uname -r
command on the host and in the container, then the same version will seem to me.
And if I ask for the "OS version" with the cat /etc/os-release
command, then the information on the host and in the container may be different, since the container contains specific versions of programs, libraries, etc., that is, everything that is already " above the core.
Also, I understand the cardinal differences between docker containers and virtual machines.
But here's what I don't understand.
Processes.
I count the number of running processes with the command ps -A --no-headers | wc -l
When I count the number of running processes on my toy server under ubuntu, I get the number 184.
I will take the simplest Dockerfile, consisting of one line FROM Ubuntu 20.04
I will run it with the command
docker run --entrypoint "/bin/bash" --name u20 -it ubuntu20-img
just run ubuntu in container and container in interactive mode
The process counter on the host will then show 187 processes – three more. The process counter inside the container shows… 3 processes. And I even understand which ones: these are bash, ps and wc
Question: why so few? After all, I have, after all, a whole ubuntu?
Why is it, being launched in a container, content with one single process?
I see the logic and correspondence of the docker idology "one container – one function – one process" here.
But I don’t understand how exactly the Ubuntu running in the container – in the sense of its processes – is so different from the one that runs on the host.
In general, I would like to read a little more about how docker works at a low level – how a container is launched, what happens when a docker exec
is executed, etc.
I tried the book "McKendrick R., Gallagher S. – Mastering Docker. Third Edition", watched several docker videos and read about twenty articles. But they are all built according to the same pattern "difference with VM – advantages – container creation commands" – and drove, drove towards assembly, orchestration and use. Aside how to use docker. No one writes about how it works and what happens at the system level when executing commands.
Could you direct me to the correct sources in which these points are explained?
Answer:
Consider a simple example where one container is started:
docker run -ti ubuntu /bin/bash
From the point of view of the OS, this is a normal process to which certain settings are applied in order to:
- limit the resources available to this process (i.e. memory, CPU time, IO, etc.)
- isolate the process from other processes running in the OS
- isolate the OS file system from our process
For this, the mechanisms implemented by the Linux kernel are used:
- cgroups (control groups): allows you to set limits on consumed resources for the process, and also pause the process and restart it.
- namespaces: this feature allows you to create namespaces for system resources such as pids (process IDs), network interfaces, ports, user/group IDs, etc. See below for more details on how this works.
- ufs (union file system): allows multiple file systems to be combined into one. Used to be able to "over" read-only file system image, say the same ubuntu image, add a new "layer" that can be modified.
All these features are available in the Linux kernel and you can use them for your own purposes. docker is such a front-end that provides a convenient interface in order to use all these isolation and control features conveniently.
Namespaces
The namespace allows you to isolate system resources. For example, pids, if a process is running in a separate pid namespace, then it can only see processes from the same namespace. Those. in a "give me a list of all processes" system call to the kernel, it will only see those processes that are running in the same namespace. The system call is the same, it implements this filtering logic in itself.
It is also important that the identifiers in each space are different, i.e. Both in the "default" space and in the additionally created ones there can be processes with ID 1 and these will be different processes.
Similarly, there are namespaces for users. Those. a process can be assigned a separate namespace to which its users exist (and in that space another user will be root).
The same goes for ports. A process can be assigned its own namespace, in which the process can use port 80, despite the fact that in the OS port 80 may already be used by another process, but these ports do not overlap, since they are in different namespaces.
why so few? After all, I have, after all, a whole ubuntu?
You don't have a "whole ubuntu" in that container. Those. you don't have all the functionality that those 184 processes give you. For example, there are no processes that make sure that daemon processes are running. This is usually not necessary due to the specifics of what the containers are used for. But if it is necessary, then you will have to run them yourself inside the container.
I don’t understand how exactly the ubunta running in the container – in the sense of its processes – is so different from the one that runs on the host
It all depends on what you call "ubuntu". In the bash example above, you have one process running in the container. From the point of view of the OS ("host" of the system – I write in quotes, because I explain this for a better understanding, in fact there is no host and guest system, as in a VM) it's just one process, but which has its own namespaces assigned, to isolate it from other processes and files.
In essence, ubuntu in a container is the files that are in the file system of the image from which the container is launched. Those. there are programs from the ubuntu distribution kit (and not, say, from alpine) and they can be run inside the container.