# 6 Docker平台架构

前面讲解了镜像、容器、仓库的操作,现在回过头来简单回顾一下 Docker 的架构,应该会更清晰一些。

# 6.1 操作流程

首先通过客户端发送命令给 Docker daemon 守护进程, Docker daemon 会检查本地是否有镜像,如果没有就从远程仓库 Registry 拉取镜像,例如拉取 Redis 镜像,拉取到本地后,运行镜像成为 Container 容器,就是一个运行的 Redis 了,每个容器之间是相互隔离的,就像一个个的集装箱,所以 Docker 的图标就是一个鲸鱼上面有很多的集装箱。

# 6.2 镜像的分层原理

现在回过头来看一下镜像。

镜像是一种轻量级、可执行的独立软件包,包含运行某个应用程序所需要的所有内容,我们把应用程序和它所需要的配置依赖打包形成一个可交付的运行环境,这个打包好的运行环境就是镜像文件。


我们前面在拉取 redis 镜像的时候,会发现下载的过程如下:

会看到镜像是一部分一部分的被下载。

这是因为 Docker 镜像实际上由一层一层的文件系统组成,这种层级的文件系统是 UnionFs(联合文件系统),上面每一个被下载的部分就是镜像的一层。


bootfs(boot file system)是 Docker 镜像的最底层的一层,主要包含引导程序(bootloader)和内核(Kernel),这一层与标准的 Linux/Unix 系统是一样的。当计算机启动时,它会首先加载这一层,然后由引导程序加载内核到内存中。之后,内存的使用权会从这一层转移到内核,然后这一层就会被卸载,释放出存储空间。

rootfs(root file system)在 bootfs之上,也就是上图中的 Base Image 这一层,这是操作系统工作的主要文件系统。它包含了操作系统的所有核心文件和目录,例如 /dev(设备文件)、/proc(进程信息)、/bin(可执行文件)、/etc(配置文件)等。不同的操作系统发行版(如 Ubuntu、CentOS 等)都有自己的 rootfs,因为它们包含的文件和目录会有所不同。所以前面说过:每个容器都可以看作是一个简易版的 Linux 环境,就在这一层提供了。 为什么 Ubuntu 镜像那么小,因为只提供了bootfs和rootfs。

当我们需要什么功能,在这些层上添加就可以了,例如需要 emacs,就添加 emacs 镜像层,需要 Apache web 服务器,就添加 Apache 镜像层。这些层按照创建顺序叠加在一起,形成了完整的镜像。每一层都是只读的,保证了镜像的完整性和一致性。

Docker 镜像层都是只读的,当我们使用镜像创建容器时,Docker 会在顶层添加一个新的层,这一层是容器层,是可写的,可以在其中进行修改,而底层的所有层则保持不变。 这种分层的设计使得镜像的复用和共享变得非常容易,比如有多个镜像都从相同的Base Image构建而来,那么宿主机只需在磁盘上保留一份Base Image,同时内存中也只需要加载一份Base Image,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享,减小了传输和存储的开销。