Docker 镜像分层、镜像摘要
镜像分层
镜像摘要
镜像分层
Docker 镜像由一些松耦合的只读镜像层组成,Docker Daemon 负责堆叠这些镜像层,并 将它们关联为一个统一的整体,即对外表现出的是一个独立的对象。 通过 docker pull 命令拉取指定的镜像时,每个 Pull complete 结尾的行就代表下载完毕了 一个镜像层。
示例:
为什么要分层
分层结构的最大的好处是,在不同镜像间实现 资源共享 。即不同镜像对相同下层 镜像的复用。对于 docker pull 命令,其在拉取之前会先获取到其要拉取镜像的所有 ImageID, 然后在本地查找是否存在这些分层。如果存在,则不再进行拉取,而是共享本地的该分层。 大大节点的存储空间与网络带宽,提升了拉取效率。
镜像层的构成
每个镜像层由两部分构成:镜像文件系统 与 镜像 json 文件 。这两部分具有相同的 ImageID。
镜像文件系统就是对镜像占有的磁盘空间进行管理的文件系统,拥有该镜像所有镜像层 的数据内容。而镜像 json 文件则是用于描述镜像的相关属性的集合,通过 docker inspect [镜像]
就可以直观看到。
镜像文件系统的构成
一个 docker 镜像的文件系统 FS 由多层只读的镜像层组成,每层都完成了特定的功能。 而这些只读镜像层根据其位置与功能的不同可分为两类:基础镜像层与扩展镜像层。
基础镜像层
所有镜像的最下层都具有一个可以看得到的基础镜像层 Base Image,基础镜像层的文件 系统称为根文件系统 rootfs。而 rootfs 则是建立在 Linux 系统中“看不到的”引导文件系统 bootfs 之上。
扩展镜像层
在基础镜像层之上的镜像层称为扩展镜像层。顾名思义,其是对基础镜像层功能的扩展。 在 Dockerfile 中,每条指令都是用于完成某项特定功能的,而每条指令都会生成一个扩展镜 像层
容器层
一旦镜像运行了起来就形成了容器,而容器就是一个运行中的 Linux 系统,其也是具有 文件系统的。容器的这个文件系统是在 docker 镜像最外层之上增加了一个可读写的容器层, 对文件的任何更改都只存在于容器层。因此任何对容器的操作都不会影响到镜像本身。
容器层如果需要修改某个文件,系统会从容器层开始向下一层层的查找该文件,直到找 到为止。任何对于文件的操作都会记录在容器层。例如,要修改某文件,容器层会首先把在 镜像层找到的文件 copy 到容器层,然后再进行修改。删除文件也只会将存在于容器层中的 文件副本删除。
可以看出,Docker 容器就是一个叠加后的文件系统,而这个容器层称为 Union File System, 联合文件系统。
镜像摘要
每个镜像都有一个长度为 64 位的 16 进制字符串作为其摘要 digest。
查看摘要
通过 docker inspect
命令可以查看指定镜像的详细信息。其中就包含该镜像的摘要信息。
docker inspect [OPTIONS] NAME|ID [NAME|ID...]
通过 docker images --digests
命令也可以查看到镜像的摘要信息
摘要是什么
摘要,即 digest,是镜像内容的一个 Hash 值,即所谓的 Content Hash(内容散列)。
Docker 默认采用的 Hash 算法是 SHA256。
摘要有何用
区分相同 <repository>:<tag>
的不同镜像
分发散列值
在 push 或 pull 镜像时,都会对镜像进行压缩以减少网络带宽和传输时长。但压缩会改变镜像内容,会导致经过网络传输后,镜像内容与其 digest 不相符。出现问题。 为了避免该问题,Docker 又为镜像配置了 Distribution Hash(分发散列值)。在镜像被压缩后立即计算分发散列值,然后使该值随压缩过的镜像一同进行发送。在接收方接收后,立即计算压缩镜像的分发散列值,再与携带的分发散列值对比。如果相同,则说明传输没有问题。
多架构镜像
查看 dockerhub 的一些镜像发现,同一 tag 对应多种不同架构镜像:
什么是 多架构镜像
Multi-architecture Image,即多架构镜像,是某 <repository>
中的某 <tag>
镜像针对不同操作系统/系统架构的不同镜像实现。即多架构镜像中包含的镜像的 <repository>:<tag>
都是相同的,但它们针对的操作系统/系统架构是不同的。
无论用户使用的是什么操作系统/系统架构,其通过 docker pull 命令拉取到的一定是针 对该操作系统/系统架构的镜像,无需用户自己考虑操作系统/系统架构问题。Docker Hub 能 够根据提交 pull 请求的 Docker 系统的架构自动选择其对应的镜像。
原理 多架构镜像
在 Docker Hub 中,镜像的多架构信息保存在 Manifest 文件中。在拉取镜像时,Docker 会随着 pull 命令将当前 Docker 系统的 OS 与架构信息一并提交给 Docker Hub。Docker Hub 首 先会根据镜像的 <repository>:<tag>
查找是否存在 Manifest。如果不存在,则直接查找并返回 <repository>:<tag>
镜像即可;如果存在,则会在 Manifest 中查找是否存在指定系统/架构的镜像。如果存在该系统/架构,则根据 Manifest 中记录的地址找到该镜像的位置。