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

c6ubokkw  于 2022-12-29  发布在  Docker
关注(0)|答案(2)|浏览(239)

Docker如何在Debian主机上运行,比如一个容器中的OpenSUSE?它使用不同的内核,有独立的模块。而且旧的Debian版本使用旧的内核,那么如何在内核版本3.10+上运行它?旧的内核只有旧的内置函数,旧的发行版如何管理新的特性?它的“诀窍”是什么?

oxiaedzo

oxiaedzo1#

Docker从不使用不同的内核:内核始终是宿主内核。
如果你的主机内核与你想运行的容器中的软件“足够兼容”,它就会工作;否则就不会。

“容器”只是流程配置

要理解的关键是Docker容器 * 不是 * 虚拟机:它不会创建一个新的虚拟计算机来运行软件,而是在现有的操作系统中启动进程,就像你从命令行启动新进程一样。
“容器化”流程与普通流程的区别在于对容器化流程的限制以及对它如何查看周围环境的更改。(这些更改将传递给容器化流程启动的任何子流程。)典型的限制和更改包括:

  • 不使用主机的根文件系统,而是在/上挂载一个不同的文件系统(通常与容器的映像一起提供)。主机文件系统的一部分可以挂载在新进程的根文件系统之下,例如通过使用docker run -v /u/myprogram-data:/var/data/myprogram,以便当容器化进程读或写/var/data/myprogram/file时,它读/写主机文件系统中的/u/myprogram-data/file
  • 为容器化进程创建一个单独的进程空间,以便它只能看到自己及其子进程(使用ps或类似命令),但不能看到主机上运行的其他进程。
  • 创建单独的用户命名空间,以便容器中的用户与主机中的用户不同:例如,容器化进程中的UID 1234与非容器化进程中的UID 1234不同
  • 创建一组具有自己IP地址的单独网络接口,通常使用“虚拟路由器”以及这些接口与主机网络接口之间的地址转换。(例如,当主机在端口8080上接收到数据包时,将其转发到容器进程的虚拟网络接口上的端口80。)

所有这些都是由内置在内核中的工具完成的;如果您编写一个程序来进行适当的设置,并在它启动新进程时设置适当的参数,那么您可以在没有Docker的情况下自己完成其中的任何一项。

兼容性

那么“足够兼容”是什么意思呢?它取决于程序对内核发出了什么请求(系统调用),以及它期望内核支持什么特性。有些程序发出的请求会破坏东西;例如,在Ubuntu 18.04(kernel 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或更早版本,您会发现它工作得很好(至少在我测试的时候是这样)。

u91tlkcl

u91tlkcl2#

Docker如何在Debian主机上运行呢?可能是容器中的OpenSUSE
因为内核是相同的,并且将支持Docker引擎来运行所有这些容器映像:主机内核应该是3.10或更高,但它的list of system calls相当稳定。
参见“Architecting Containers: Why Understanding User Space vs. Kernel Space Matters“:
1.应用程序包含业务逻辑,但依赖于系统调用。
1.一旦应用程序被编译,应用程序使用(即依赖)的系统调用集就被嵌入到二进制文件中(在高级语言中,这是解释器或JVM)。
1.容器并不抽象用户空间和内核空间共享一组公共系统调用的需要。
1.在集装箱化的世界中,这些用户空间被捆绑在一起,并被运送到不同的主机上,从笔记本电脑到生产服务器。
1.在未来几年,这将带来挑战。

有时会添加新的系统调用,而旧的系统调用会被弃用;当考虑容器基础结构的生命周期和在其中运行的应用程序时,应该考虑到这一点。
另请参见“为什么内核版本与Docker容器中的Ubuntu版本不匹配?":
容器中没有内核。即使你安装了内核,它也不会在容器启动时被加载。容器的真正目的是隔离进程而无需运行新的内核。

相关问题