镜像分层
Docker 镜像由一些松耦合得只读镜像层组成,Docker Daemon 负责堆叠这些镜像层,并将他们管理为一个整体,对外表现出得是一个独立得对象。
docker pull 拉取镜像时,每个pull complete 行就代表下载了一个镜像层,比如:


为什么分层
分层得优势有:
- 每个分层只读,对分层得修改都是以新分层得形式出现,不会破坏原分层内容
- 每个分层只记录变更内容,所以节省空间
- 不同镜像间实现资源共享,即不同镜像对相同下层镜像得复用。
docker pull 在拉取之前会先获取要拉取镜像的所有imageID,然后再本地查找这些分层。如果存在,不再拉取,而是共享本地的分层,节省了空间和网络带宽。提高了拉取效率。
镜像层构成
每个镜像层由两部分构成:镜像文件系统和镜像json文件。他们具有相同的imageID。
镜像文件系统:拥有镜像所有镜像层的数据内容。
镜像json文件:描述镜像相关属性的集合,通过docker inspect 【镜像】可以查看。
镜像FS构成
docker镜像文件系统FS 由多个只读的镜像层组成,每层都有特定的功能。
这些只读镜像层根据位置与功能不同可分为两类:基础镜像层和扩展镜像层。

基础镜像层
所有镜像的最下层都有一个看得到的基础镜像层Base Image,基础镜像层的文件系统称为根文件系统rootfs。
而rootfs 是建立在Linux中“看不到的”引导文件系统bootfs 之上。
扩展镜像层
在基础镜像层之上的镜像层称为扩展镜像层,是对基础镜像层功能的扩展。
在Dockerfile 中。每条指令都是用于完成特定功能,而每个指令都会生产一个扩展镜像层。
容器层

镜像运行起来就成了容器,而容器也具有文件系统。
容器的文件系统在docker镜像最外层之上增加了一个可读写的容器层。
对文件的任何更改只存在于容器层,因此不会影响镜像本身。
容器要修改某个文件,会从容器层开始向下一层层的查找,直到找到为止,对文件的操作都会记录在容器层。
比如:要修改某个文件,容器层会在镜像层找到文件并copy到容器层,然后再进行修改。删除文件也只会将容器层中的文件副本删除。
可以看出,Docker容器就是一个叠加后的文件系统,这个容器层称为Union FIle System 联合文件系统。
Linux OS 启动过程

微内核架构分为内核(Server)和服务模块(Client)。
LInux 的bootfs 由两部分组成:bootloader 和kernel
各个容器中的rootfs 就是由宿主机的kernel驱动的。

镜像摘要(digest)
每个镜像都有一个长度为64位的16禁止字符串作为其摘要digest。
#查看摘要 方式一
docker inspect zookeeper:latest
# 查看摘要方式二
docker images zookeeper --digest
摘要是什么
摘要(digest) 是镜像内容的一Hash值,即所谓的Content Hash,只要镜像内容发生变化,其内容散列值就会改变。
默认的Hash算法是sha256
摘要的作用
区分相同<repository>:<tag>的不同镜像。
比如:镜像xxx:2.8 在运行中发现bug,然后进行了修复,然后使用原标签将其push回仓库,原镜像被覆盖。
但是生产环境中海油运行中未修复的镜像容器。此时标签无法区分镜像是修复前还是修复后,这时就只能查看digest 。
分发散列值
在push或pull时,都会对镜像进行压缩以减少网络带宽。但压缩会改变镜像内容,导致传输后与digest不符合。
为了解决这个问题,Docker 为镜像配置了Distribution Hash(分发散列值)。在镜像压缩后计算分发散列值,然后随镜像一同发生。接受方拿到后,立即计算压缩后镜像的分发散列值,与携带的分发散列值对比。如果相同,则传输没问题。
多架构镜像
Multi-architecture Image 多架构镜像,是某个镜像针对不同操作系统/系统架构 的不同镜像实现。
即镜像的<repository>:<tag>是相同的,但是针对的操作系统/系统架构不同。
多架构镜像原理
无论用户使用的是什么操作系统,通过docker pull 拉去到的一定是针对该操作系统的镜像,用户无需考虑操作系统问题。
Docker Hub能根据pull请求自动选择对应的镜像。

镜像的多架构信息保存在Mainifest 文件中。
拉取镜像时,pull命令将OS与架构信息一并提交给Docker Hub。
Docker Hub根据<repository>:<tag>查找Manifest。如果不存在,直接查找并返回镜像。
如果存在。会根据Manifest 中记录的地址找到该镜像的位置。
