容器就是一个进程集合,它将系统的其他资源隔离开来,具有自己独立的资源视图。
容器就是一个视图隔离、资源可限制、独立文件系统的进程集合。所谓“视图隔离”就是能够看到部分进程以及具有独立的主机名等;控制资源使用率则是可以对于内存大小以及 CPU
使用个数等进行限制。容器具有一个独立的文件系统,因为使用的是系统的资源,所以在独立的文件系统内不需要具备内核相关的代码或者工具,我们只需要提供容器所需的二进制文件、配置文件以及依赖即可。只要容器运行时所需的文件集合都能够具备,那么这个容器就能够运行起来。
我们将这些容器运行时所需要的所有的文件集合称之为容器镜像。这些镜像如何运行在生产环境或者测试环境上呢?这时候就需要一个中转站或者中心存储,我们称之为 docker registry,也就是镜像仓库,其负责存储所有产生的镜像数据。我们只需要通过 docker push
就能够将本地镜像推动到镜像仓库中,这样一来,就能够在生产环境上或者测试环境上将相应的数据下载下来并运行了。那么容器该如何运行呢?
- 从镜像仓库中将相应的镜像下载下来
- 当镜像下载完成之后就可以通过
docker images
来查看本地镜像,这里会给出一个完整的列表,我们可以在列表中选中想要的镜像 - 当选中镜像之后,就可以通过
docker run
来运行这个镜像得到想要的容器,当然可以通过多次运行得到多个容器
生命周期
容器是一组具有隔离特性的进程集合,在使用 docker run
的时候会选择一个镜像来提供独立的文件系统并指定相应的运行程序。这里指定的运行程序称之为 initial
进程,这个 initial
进程启动的时候,容器也会随之启动,当 initial
进程退出的时候,容器也会随之退出。initial
进程本身也可以产生其他的子进程或者通过 docker exec
产生出来的运维操作,也属于 initial
进程管理的范围内。当 initial
进程退出的时候,所有的子进程也会随之退出,这样也是为了防止资源的泄漏。
数据卷
当一个容器退出被删除之后,数据也就会丢失了,这对于应用方而言是不能接受的,所以需要将容器所产生出来的重要数据持久化下来。容器能够直接将数据持久化到指定的目录上,这个目录就称之为数据卷。数据卷有一些特点,其中非常明显的就是数据卷的生命周期是独立于容器的生命周期的,也就是说容器的创建、运行、停止、删除等操作都和数据卷没有任何关系,因为它是一个特殊的目录,是用于帮助容器进行持久化的。简单而言,我们会将数据卷挂载到容器内,这样一来容器就能够将数据写入到相应的目录里面了,而且容器的退出并不会导致数据的丢失。
通常情况下,数据卷管理主要有两种方式:
bind
的方式:直接将宿主机的目录直接挂载到容器内;这种方式比较简单,但是会带来运维成本,因为其依赖于宿主机的目录,需要对于所有的宿主机进行统一管理。- 目录管理交给运行引擎
引擎架构
moby
是目前最流行的容器管理引擎,moby daemon
会对上提供有关于容器、镜像、网络以及 Volume
的管理。moby daemon
所依赖的最重要的组件就是 containerd
,containerd
是一个容器运行时管理引擎,其独立于 moby daemon
,可以对上提供容器、镜像的相关管理。containerd
底层有 containerd shim
模块,其类似于一个守护进程,这样设计的原因有几点:
- 首先,
containerd
需要管理容器生命周期,而容器可能是由不同的容器运行时所创建出来的,因此需要提供一个灵活的插件化管理。而shim
就是针对于不同的容器运行时所开发的,这样就能够从containerd
中脱离出来,通过插件的形式进行管理。 - 其次,因为
shim
插件化的实现,使其能够被containerd
动态接管。如果不具备这样的能力,当moby daemon
或者containerd daemon
意外退出的时候,容器就没人管理了,那么它也会随之消失、退出,这样就会影响到应用的运行。 - 因为随时可能会对
moby
或者containerd
进行升级,如果不提供shim
机制,那么就无法做到原地升级,也无法做到不影响业务的升级,因此containerd shim
非常重要,它实现了动态接管的能力。
Docker
参考资料
云原生技术公开课
[