Docker 运行 发行版如何使用不同的内核?

How can Docker run distros with different kernels?

Debian 主机上的 docker 运行 怎么可能是容器中的 OpenSUSE?它使用不同的内核,具有分离的模块。较旧的 Debian 版本也使用较旧的内核,那么 运行 它怎么能在内核版本 3.10+ 上使用呢?较旧的内核只有较旧的内置功能,旧发行版如何管理新功能? "the trick"里面是什么?

How can docker run on a Debian host maybe an OpenSUSE in a container

因为内核是相同的,并且将支持 Docker 引擎到 运行 所有这些容器镜像:主机内核应该是 3.10 或更高版本,但它的 list of system calls 相当稳定。

参见“Architecting Containers: Why Understanding User Space vs. Kernel Space Matters”:

  1. Applications contain business logic, but rely on system calls.
  2. Once an application is compiled, the set of system calls that an application uses (i.e. relies upon) is embedded in the binary (in higher level languages, this is the interpreter or JVM).
  3. Containers don’t abstract the need for the user space and kernel space to share a common set of system calls.
  4. In a containerized world, this user space is bundled up and shipped around to different hosts, ranging from laptops to production servers.
  5. Over the coming years, this will create challenges.

From time to time new system calls are added, and old system calls are deprecated; this should be considered when thinking about the lifecycle of your container infrastructure and the applications that will run within it.

另见“Why kernel version doesn't match Ubuntu version in a Docker container?”:

There's no kernel inside a container. Even if you install a kernel, it won't be loaded when the container starts. The very purpose of a container is to isolate processes without the need to run a new kernel.

Docker 从不使用不同的内核:内核始终是您的主机内核。

如果您的主机内核 "compatible enough" 带有您想要 运行 的容器中的软件,它将工作;否则不会。

"Containers"只是进程配置

要理解的关键是 Docker 容器 不是 虚拟机:它不会创建新的虚拟计算机 运行 软件。相反,Docker 只是 运行s 进程在您现有的 OS 中,其方式类似于您只是从命令行启动一个进程。

容器化进程与普通进程的区别在于对容器化进程的限制以及它对周围环境的看法发生了变化。 (这些将传递给容器化进程启动的任何子进程。)典型的限制和更改包括:

  • 不使用主机的根文件系统,而是在 / 上挂载一个不同的文件系统(通常是随容器映像一起提供的)。主机文件系统的一部分可以安装在新进程的根文件系统下,例如通过使用 docker run -v /u/myprogram-data:/var/data/myprogram 以便当容器化进程在主机文件系统中读取或写入 /var/data/myprogram/file this reads/writes /u/myprogram-data/file 时。
  • 为容器化进程创建一个单独的进程space,这样它只能看到自己和它的子进程(使用ps或类似的命令),而看不到其他进程运行宁在主机上。
  • 创建一个单独的用户名space,使容器中的用户与主机中的用户不同:例如,容器化进程中的 UID 1234 与 [=68 的 UID 1234 不同=]
  • 使用自己的 IP 地址创建一组单独的网络接口,通常使用 "virtual router" 和这些网络接口与主机网络接口之间的地址转换。 (例如,当主机在端口 8080 上接收到数据包时,会将其转发到容器进程的虚拟网络接口上的端口 80。)

所有这些都是由内核内置的工具完成的;如果您编写一个程序来执行适当的设置并在启动新进程时设置适当的参数,则无需 Docker 就可以自己完成任何操作。

兼容性

那么"compatible enough"是什么意思呢?这取决于程序对内核提出的请求(系统调用)以及它希望内核支持的功能。有些程序发出会破坏事物的请求;其他人没有。例如,在 Ubuntu 18.04(内核 4.19)或类似主机上:

  • docker run centos:7 bash 工作正常。
  • docker run centos:6 bash 失败,退出代码为 139,这意味着它以分段违规信号终止;这是因为 4.19 内核不支持构建 bash 试图做的事情。
  • docker run centos:6 ls 工作正常,因为它没有像 bash 那样发出内核无法处理的请求。

如果您尝试 docker run centos:6 bash 在较旧的内核上,比如 4.9 或更早版本,您会发现它可以正常工作。 (至少就我测试而言。)