赞
踩
Docker
引擎基于开放容器计划,所以它采用了模块化的设计原则。
Docker
引擎由许多模块组成,它的功能是创建和运行容器。
Docker
引擎主要由 Docker
客户端(Docker Client)、Docker
守护进程(Docker daemon)、containerd
、runc
(可读读作 run c)模块组成。
它的主要功能是将 Docker
命令行转换为合适的 REST API
格式,发送到 Docker
守护进程。
本篇博客撰写时,daemon
主要功能包括镜像管理、镜像构建、REST API
、身份验证、安全、核心网络以及编排。
在早期的 Docker
架构中,Docker
所有的功能都是在 Docker daemon
中,如果你是开发人员,可以理解成早期的 Docker
架构是单体架构,随着 OCI
开放容器标准的推行,Docker daemon
这个大杂烩,渐渐被拆分为多个模块了,拆分工作一直在进行。
管理容器的生命周期 —— start | stop | rm …
随着时间的推移,它被赋予了更多的功能,例如镜像管理。这不是与模块化冲突了吗?怎么又有容器,又有镜像?其原因之一在于,这样方便在其他项目中使用它,例如 Kubernetes
。不过,除了管理容器,其他功能都是额外功能,都是可选的、组件化的。
runc
被开发出来,只有一个作用 —— 创建容器,它本质是一个针对 Libcontainer
进行包装,轻量级的命令行交互工具箱。
Libcontainer
,它的前身是 LXC
,LXC
是早期 Docker
架构中的一部分,它提供了命名空间(Namespace)、控制组(CGroup)等基础工具的能力,这些基础工具是基于 Linux
内核的容器虚拟化技术,但是对 LXC
的依赖是一个问题,因为它基于 Linux
系统,对于立志跨平台的 Docker
来说不行。其次 LXC
提供的功能是容器的核心,核心的东西交给外部工具,给 Docker
项目也会带来风险,因此 Docker
开发了 Libcontainer
取代 LXC
。
shim
是容器的父进程,它的职责是保证 stdin
和 stdout
流是开启状态,当 daemon
重启的时候,容器不会因为终止。当容器退出时,shim
还会将退出状态反馈给 daemon
。
这里多说两句,提到容器的进程,不知道你有没有听过这样一句话,“Docker daemon
是无守护进程的容器”,因为 shim
才是容器进程的主人。假如没有 shim
,每次对 daemon
升级,都会导致主机上的容器被 kill
,这在生产环境是一场灾难。
shim
管理容器进程,是从 runc
那里’接手’的。当 daemon
从外部(例如 Docker Client
)收到一个创建容器的命令,它会将创建的操作告诉 containerd
,containerd
把创建的命令打包,通过 grpc
发送给 runc
,指挥 runc
创建新容器,runc
会 fork
一个新的 runc
实例,容器创建完毕后,runc
进程机会退出,新建一个 shim
进程来作为容器的父进程。
为什么不使用 runc
来作为容器的父进程呢?因为 runc
只是用来创建容器的,它只有这一个作用。
现在,容器启动完毕了,整个过程如下图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。