Docker 容器不需要操作系统,但是每个容器都有一个。为什么?

“ docker”这个词现在很流行,我想弄清楚它是什么,它是怎么工作的。更具体地说,它与普通虚拟机(比如 VirtualBox、 HyperV 或 WMWare 解决方案)有什么不同。

文档(https://docs.docker.com/get-started/#a-brief-explanation-of-containers)的导言部分内容如下:

容器在主机的内核上本机运行应用程序。与只能通过虚拟机监控程序对主机资源进行虚拟访问的虚拟机相比,它们具有更好的性能特征。容器可以获得本机访问,每个容器运行在一个独立的进程中,不会比其他任何可执行文件占用更多的内存。

找到了!这就是区别。容器直接运行在宿主操作系统的内核上,这就是为什么它们如此轻量级和快速(加上它们提供了进程隔离和以 docker hub 形式的良好分发机制,这与容器之间相互连接的能力很好地结合在一起)。

等等。我可以使用 docker 在 Windows 上运行 Linux 应用程序-这怎么可能呢?当然,有一些 VM。否则我们就完不成任务了。

好吧,但是当我们在 Linux 主机上工作的时候,它看起来是什么样子? ? ?这里有真正的困惑... 有一个仍然定义操作系统作为一个基本的映像,我们想要创建的每个映像。即使我们说“ FROM 刮擦”-刮擦仍然是一些极简主义的内核... 所以这里来了

问题1 : 如果我运行 CentOS 主机,是否可以创建容器,它将直接使用这个主机操作系统的内核(而不是包含自己操作系统的 VM) ?如果是,我怎么做?如果没有,那么为什么 docker 的文档对我们撒谎(因为 docker 映像总是在某个 VM 中运行,并且它与其他 VM 没有太大区别,或者它是否存在?)?

经过一些思考和环顾四周,我想知道,如果一些优化是为了运行图像。来了

问题2 : 如果我运行两个容器,两个容器的图像都基于同一个父图像,这个父图像将只加载到内存中一次吗?每个容器有一个 VM 还是只有一个 VM,它同时运行两个容器?如果我们使用不同的操作系统呢?

第三个问题很难回答:

问题3 : 是否有一些资源,描述这类事情... 因为大多数讨论 docker 的文章只是告诉“它是如此的酷,你一定要使用它。只要运行一个命令,就会很高兴”... 这并不能解释太多。

谢谢。

41818 次浏览

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:

  1. 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.

  2. 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.

  3. In Linux you can try man cgroups and man cgroup_namespaces to 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:

  1. 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:6 or centos:5 container on a Linux system with a 4.19 or later kernel, and you'll see that /bin/bash segfaults 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.

  2. 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.)

Docker does not has an OS in its containers. In simple terms, a docker container image just has a kind of filesystem snapshot of the linux-image the container image is dependent on.

The container-image includes some basic programs like bash-shell, vim-editor etc to facilitate developer to work easily with the docker image. Also, docker images can include pre-installed dependencies like nodeJS, redis-server etc as we can find on docker hub.

Docker behind the scene uses the host OS which is linux itself to run its containers. The programs included in linux-like filesystem snapshot that we see in form of docker containers actually runs on the host OS in isolation.

The container-images may sound like different linux distros but they are the filesystem snapshot of those distros. All Linux distributions are based on the same kernel. They differ in the programs, tools and dependencies that they ships with.

Also take note of this comment [click]. It is very much relevant to this question.

Hope this helps.

It's now long time since I posted this question, but it seems, like it still get hits... So I decided to answer it - in fact mainly the question, which is in the title (the questions in the text are carefully answered by Curt J. Sampson).

So, the discussion of the "main" question: if containers are not VMs, then why do we need VMs for them?

As you may guess, I am working on windows (on Linux this question would not emerge, because on Linux one does not need VMs for docker).

The reason, why we need a VM for containers in Winodows is pretty obvious (probably this is the reason, why nobody mentions it explicitly). As was already mentioned here and it many other FAQs, containers reuse kernel and some other resources of the hosting OS. Taking into account, that most of the containers available out there are based on Linux, one may conclude, that those containers need host OS to provide Linux kernel for them to run. Which is not natively easy on Windows (I am not sure, may be it is now possible with Linux subsystem). This is why on Windows we need one VM, which runs Linux and docker service inside this VM. And then, when we start the containers, they are also started inside this VM (and reuse the resources of its Linux OS). All the containers run inside the same VM. Getting a bit more technical: by default docker uses Hyper-V to run this linux VM, but one can also use Docker-Toolbox, which uses Oracle VirtualBox. By the way, VM can be freely seen in the Virtual Box interface. Nice part is that Docker (or Docker toolbox) takes care about managing this VM and we don't need to care about it.

Now some bonus question, which that time confused me even more. One may think: "Ok, it is clear now. If we run Linux container on Winodws OS, then we need Linux kernel and thus need VM with Linux. But if we run Windows container on Windows (by the way, it exists), then VM should not be needed, right?..." Answer: "wrong" (or almost wrong). :) The problem is, that the Windows based containers (at least those, which I saw) use windows server kernel, which is not available e.g. in Windows 10. Thus one still need VM with special version of Windows Server running on it. In fact MS even created special version of Windows Server, which can be run on VM for development purposes free of charge specifically to enable development of Windows-Server based containers. If my understanding is correct, those containers should be possible to run without VM on Windows Server. I should admit, that I never checked it though.

I hope, that this messy explanation may help someone to better understand the topic.

We need a VM to run a docker on the host machine ( this is achieved through the docker toolbox) if it is windows, on Linux we don't even need this. Once we have a docker toolbox container in itself doesn't need a VM, each container has a baseline image which is very minimal and reuses a lot of stuff with the host kernel hence making it lightweight compared to VM. You can run many such container using single host kernel.