本节书摘来自华章社区《docker进阶与实战》一书中的第2章,第2.2节一分钟理解容器,作者华为docker实践小组,更多章节内容可以访问云栖社区“华章社区”公众号查看
2.2 一分钟理解容器
2.2.1 容器的组成
上文已多次提及,容器的核心技术是cgroup + namespace,但光有这两个抽象的技术概念是无法组成一个完整的容器的。在2.1.2节也提到过最早的容器概念就包括了对文件目录视图的抽象隔离,而所有的这一切,都需要有工具来驱动,需要有一个工具来提供用户可操作的接口,来创建一个容器。所以笔者认为,对于linux容器的最小组成,可以由以下公式来表示:
容器 = cgroup + namespace + rootfs + 容器引擎(用户态工具)
其中各项的功能分别为:
cgroup:资源控制。
namespace:访问隔离。
rootfs:文件系统隔离。
容器引擎:生命周期控制。
目前市场上所有linux容器项目都包含以上组件。
2.2.2 容器的创建原理
至此对容器的描述还一直停留在文件和概念的层面,本小节将通过简单的代码抽象,清晰地展现容器的创建原理,使读者对容器有更深刻的理解。
代码一:
对于代码一,通过clone系统调用,并传入各个namespace对应的clone flag,创建了一个新的子进程,该进程拥有自己的namespace。根据以上代码可知,该进程拥有自己的pid、mount、user、net、ipc、uts namespace。
对于代码二,将代码一中产生的进程pid写入各个cgroup子系统中,这样该进程就可以受到相应cgroup子系统的控制。
对于代码三,该fun函数由上面生成的新进程执行,在fun函数中,通过pivot_root系统调用,使进程进入一个新的rootfs,之后通过exec系统调用,在新的namespace、cgroup、rootfs中执行“/bin/bash”程序。
通过以上操作,成功地在一个“容器”中运行了一个bash程序。对于cgroup和namespace的技术细节,将在以下两节详细描述。