做Linux相关的基础性实验,让更多的读者了解Linux能做哪些工作,对Linux更感兴趣,在学习Linux的路上,你我结伴而行。讲原理是最难的环节,深入浅出,游刃有余的前提是需要对Docker技术有深入的钻研,并能用通俗易懂的易于大众接受的文字描述,本篇文章将作第一次尝试,有哪里表述不对的,请读者在文后留言。文章中很大一部分内容来源于网络,由我剪辑,如有侵犯网络作者文章,请联系我,我会做相关处理。

Docker有三组件、三要素、三个系统功能,其中三个系统功能为支柱。
Namespaces
充当隔离的第一级。确保一个容器中运行一个进程而且不能看到或影响容器外的其它进程。Control Groups
是LXC的重要组成部分,具有资源核算与限制的关键功能。UnionFS
(文件系统)作为容器的构建块。为了支持Docker的轻量级以及速度快的特性,它创建了用户层。
三个组件:
Docker Client
是用户界面,它支持用户与Docker Daemon
之间通信。Docker Daemon
运行于主机上,处理服务请求。Docker Index
是中央registry,支持拥有公有与私有访问权限的Docker容器镜像的备份。
三个基本要素:
Docker Containers
负责应用程序的运行,包括操作系统、用户添加的文件以及元数据。Docker Images
是一个只读模板,用来运行Docker容器。DockerFile
是文件指令集,用来说明如何自动创建Docker镜像。

一切均是从Docker Client
命令开始的,在基础层面上,Docker Client
会告诉Docker Daemon
需要创建的镜像以及需要在容器内运行的命令。当Daemon接收到创建镜像的信号后,会进行如下操作,为方便阅读粉色方框代表只读,绿色方框代表可写。
1、构建镜像
Docker Images是一个构建容器的只读模板,它包含了容器启动所需的所有信息,包括运行程序和配置数据。镜像可以用Docker File手工构建,原理为每个镜像都源于一个基本的镜像,然后根据Dockerfile中的指令创建模板,每一条指令就是在原有镜像上,添加新的层面。镜像就是一堆只读层的统一视角。如下图所示

从左边我们看到了多个只读层,它们重叠在一起。除了最下面一层,其它层都会有一个指针指向下一层。这些层是Docker内部的实现细节,且能够宿主机的文件系统上访问到。统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。即图片右边看到这个视角的形式。
2、运行容器
容器(container)的定义和镜像(image)几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。

容器的定义中并没有提及容器是否在运行。
Docker Registry就是存放Image的仓库。
镜像跟容器的堆层显示,下面图示用公式 容器 = 镜像 + 读写层 来了解更清晰。

说完了上面的,我们继续从文件系统(Union File System)视角探索运行态的容器以及Docker 的常用命令。
运行态容器的定义:一个可读写的统一文件系统加上隔离的进程空间和包含其中的进程。

镜像层(image layer)的定义是为了将零星的数据整合起来,

元数据(metadata)就是关于这个层的额外信息,它不仅能够让Docker获取运行和构建时的信息,还包括父层的层次信息。需要注意,只读层和读写层都包含元数据。

除此之外,每一层都包括了一个指向父层的指针。如果一个层没有这个指针,说明它处于最底层。

结合上面的讲解,我们重新理解一下Docker的常用命令。
docker create image-id

docker create 命令为指定的镜像(image)添加了一个可读写层,构成了一个新的容器,如下图

docker start <container-id>

docker start命令为容器文件系统创建了一个进程隔离空间。注意,每一个容器只能够有一个进程隔离空间。
docker run <image-id>

仅从图片来看docker start 与docker run两个命令有点类似,但也有些区别,下面一图读懂两个命令。

docker run 命令先是利用镜像创建了一个容器,然后运行此容器。
docker ps--列出所有运行中的容器,不包括非运行态容器

docker ps -a --命令会列出所有的容器,不管是运行的,还是停止的。

docker images

docker images命令列出了所有顶层(top-level)镜像。实际上,没有办法区分一个镜像和一个只读层,所以我们提出了top-level镜像。只有创建容器时使用的镜像或者是直接pull下来的镜像能被称为顶层(top-level)镜像,并且每一个顶层镜像下面都隐藏了多个镜像层。
docker images –a--命令列出了所有的镜像,也可以说是列出了所有的可读层。如果你想要查看某一个image-id下的所有层,可以使用docker history来查看

docker stop <container-id>--向运行中的容器发送一个SIGTERM的信号,然后停止所有的进程。

docker kill <container-id>--向运行中的容器发送一个SIGKILL的信号.
docker rm <container-id>--移除构成容器的可读写层。注意,这个命令只能对非运行态容器执行。

docker rmi <image-id>--移除构成镜像的一个只读层。你只能够使用docker rmi来移除最顶层(top level layer)(也可以说是镜像),你也可以使用-f参数来强制删除中间的只读层。

docker commit <container-id>--将容器的可读写层转换为一个只读层,这样就把一个容器转换成了不可变的镜像,其过程如下面两张图展示。


docker buid--docker file创建镜像。

docker build命令非常有趣,它会反复的执行多个命令。

build命令根据Dockerfile文件中的FROM指令获取到镜像,然后重复地1)run(create和start)、2)修改、3)commit。在循环中的每一步都会生成一个新的层,因此许多新的层会被创建。
docker exec <running-container-id>--在运行中的容器执行一个新进程。

docker inspect <container-id> or <image-id>--会提取出容器或者镜像最顶层的元数据,说白了就是把MD给提取出来。

docker save <image-id>--创建一个镜像的压缩文件,这个文件能够在另外一个主机的Docker上使用。和export命令不同,这个命令为每一个层都保存了它们的元数据。这个命令只对镜像生效。

docker export <container-id>--创建一个tar文件,并且移除了元数据和不必要的层,将多个层整合成了一个层,只保存了当前统一视角看到的内容。

学习操作系统时,都会学习什么是进程,简单通俗讲,进程就是一个运行的程序,如果出现死循环,CPU资源被占用完,如果内存泄漏或者大内存分配,系统内存很快就会用完,因为进程间共用了CPU和内存,此种方式,会遇到相互干扰的问题,在企业生产过程中, 任何一个小程序都会导致整个系统的崩溃。Linux出现了进程间的资源隔离技术,衍化至今,形成了三大核心功能:CGroup(限定进程的资源使用),Namespace(同一操作系统中,有些资源是全局的,为实现隔离,使用Namespace划分不同的命名空间)和UnionFS(处理分层镜像功能)。Docker的三个系统功能应该算是说透了。
Docker的三个要素也通过上文中的UnionFS方式解释的命令说透了,Docker的三个组件了流程也很简单,Client是发起者,也是需求方,直接发布需求,docker daemon接到了Cient端的需求,从Registry仓库中获取镜像,你可以理解为获取了一张只有读权限的光盘,拿着光盘你可以建立容器,提供专业化服务。镜像容器等都是有生命周期的,新建,删除、修改、查看等操作全被用专业话的术语表达。例如docker rmi 镜像等等。
本文利用UnionFS原理对Docker命令阐述的方法来源于文章:
十张图了解Docker。链接地址为 http://www.chinacloud.cn/show.aspx?id=27909&cid=81
如果您喜欢我的文章,请长按标识符关注我的公众号,学习Linux的路上,期待与您同行。





