Docker “containers” are not virtual machines; they are just regular processes running on the host system (and thus always on the host’s Linux kernel) with some special configuration to partition them off from the rest of the system.
You can see this for yourself by starting a process in a container and doing a ps outside the container; you’ll see that process in the host’s list of all processes. Running ps in the containerized process, however, will show only processes in that container; limiting the view of processes on the system is one of the facilities that containerization provides.
The container is also usually given a limited or separate view of many other system resources, such as files, network interfaces and users. In particular, containerized processes are often given a completely different root filesystem and set of users, making it look almost as if it’s running on a separate machine. (But it’s not; it still shares the host’s CPU, memory, I/O bandwidth and, most importantly, Linux kernel of the host.)
To answer your specific questions:
-
On CentOS (or any other system), all containers you create are using the host’s kernel. There is no way to create a container that uses a different kernel; you need to start a virtual machine for that.
-
The image is just files on disk; these files are “loaded into memory” in the same way any files are. So no, for any particular disk block of a file in a shared parent image there will never be more than one copy of that disk block in memory at once. However, each container has its own private “transparent” filesystem layer above the base image layer that is used to handle writes, so if you change a file the changed blocks will be stored there, and will now be separate from the underlying image that that other processes (who have not changed any blocks in that file) see.
-
In Linux you can try
man cgroupsandman cgroup_namespacesto get some fairly technical details about the cgroup mechanism, which is what Docker (and any other containerization scheme on Linux) uses to limit and change what a containerized process sees. I don’t have any other particular suggestions on readings directly related to this, but I think it might help to learn the technical details of how processes and various other systems work on Unix and POSIX systems in general, because understanding that gives you the background to understand what kinds of things containerization does. Perhaps start with learning about the chroot(2) system call and programming with it a bit (or even playing around with the chroot(8) program); that would give you a practical hands-on example of how one particular area of containerization.
Follow-up questions:
-
There is no kernel version matching; only the one host kernel is ever used. If the program in the container doesn’t work on that version of that kernel, you’re simply out of luck. For example, try runing the Docker official
centos:6orcentos:5container on a Linux system with a 4.19 or later kernel, and you’ll see that/bin/bashsegfaults when you try to start it. The kernel and userland program are not compatible. If the program tries to use newer facilities that are not in the kernel, it will similarly fail. This is no different from running the same binaries (program and shared libraries!) outside of a container. -
Windows and Macintosh systems can’t run Linux containers directly, since they’re not Linux kernels with the appropriate facilities to run even Linux programs, much less supporting the same extra cgroup facilities. So when you install Docker on these, generally it installs a Linux VM on which to run the containers. Almost invariably it will install only a single VM and run all containers in that one VM; to do otherwise would be a waste of resources for no benefit. (Actually, there could be benefit in being able to have several different kernel versions, as mentioned above.)