一、容器的目的、本质是什么
从容器(container)的名字上,我们就能够非常直观地看出容器的优点,“提供的原材料(镜像)一样,得到的结果(运行实例)一样”、“打包隔离”、“轻松运输” 等。
如果把容器类比成集装箱的话,那运行的服务或服务对应的多个进程就应该是集装箱里对应的货物了,可以很自然地想到,容器的目的就是为进程集合提供一个独立的运行环境。那我们具体应该怎么实现 “独立的运行环境” 呢?
1. 文件系统隔离
- 每个容器都具有独立的文件系统,单个容器内对文件系统进行增删改查不会影响到其他容器
- 参考 Linux 下的 chroot 命令,可以将子目录变为根目录
2. 资源隔离
- 利用 namespace 隔离进程之间的相互可见及通信
- 使用 Cgroup 限制资源使用率,设置其能够使用的 CPU 以及内存量的大小
所以容器的本质就是一个视图隔离、资源可限制、独立文件系统的进程集合,它将系统的其他资源隔离开来,具有自己独立的资源视图。“视图隔离”,指的是能够看到部分进程、有独立的主机名,“资源可限制”,指的是可以限制内存大小、CPU 使用个数等。
二、镜像是什么
我们之前提到过,容器有一个独立的文件系统,它包含了容器运行时所需要的全部文件。我们将容器运行时所需要的所有文件集合称为容器镜像。
那我们怎么去生成容器的镜像呢?一般来讲,我们会通过 Dockerfile 来构建镜像,通过 Dockerfile 的语法糖我们可以很方便的构建一个镜像,这个语法糖我们会在之后学到。
有了自己的镜像之后,我们会想,能不能把镜像都放在一个地方统一管理,就像 GitHub 一样,可以把自己的镜像分享给别人,也可以直接使用别人的镜像,于是我们把镜像放置、统一管理的地方,称之为镜像仓库。我们可以像操作 GitHub 那样(push、pull)对镜像进行操作。
三、如何得到容器
- 构建一个镜像,可以直接从镜像仓库拉取,也可以自己手动生成,目的是为容器提供生成它所需要的一切
- 运行镜像得到想要的容器
进行到这里,我们先对容器和镜像小小的总结一下:
- 一个镜像相当于一个模版,一个容器就像是这个模版生成的具体的运行实例
- 运行一个容器,就是选择某一个镜像来提供独立的文件系统并指定相应的运行程序
很明显地,容器的生命周期就和我们指定的运行程序的生命周期一致,我们也叫这个运行程序为 initial 进程,initial 进程也可以产生其他子进程。当 initial 进程退出时 ,所有的子进程也会随之退出。这样看起来,管理容器就约等于管理运行程序了。
但是这样的话,initial 进程退出,所有子进程也退出,运行程序运行产生的一些数据我们怎么能拿到并且持久化到指定目录上呢?数据卷的概念就应运而生了。
容器可以将数据持久化到指定的目录上,这个目录就叫做数据卷。数据卷最明显的特点就是,它的生命周期是独立于容器的生命周期的。
数据卷的管理方式
- 将目录直接挂载在容器内部,这种方式最简单,但是却提高了运维成本
- 运行引擎管理
|