Docker镜像的文件内容以及一些运行Docker容器的配置文件组成了Docker容器的静态文件系统运行环境,即rootfs。
Docker容器启动时,Docker daemon为Docker容器挂载一个只读(read-only)的rootfs,挂载完毕之后,利用联合挂载(union mount)技术在已有的只读rootfs上再挂载一个读写层。
1.Docker镜像设计关键技术
主要有以下关键技术。
1.1.分层
每个镜像由一系列“镜像层”组成。当需要修改容器镜像内的某个文件时,只对最上方的读写层进行变动,不复写下层已有文件系统的内容。docker commit这个修改过的容器文件系统为一个新的镜像时,保存的内容仅为最上层读写文件系统中被更改过的文件。分层达到了不同镜像之间共享镜像层的效果。
1.2.写时复制
Docker镜像采用写时复制(copy-on-write)策略,在多个容器之间共享镜像,每个容器在启动的时候不需要单独复制一份镜像文件,而是将所有镜像层以只读方式挂载到一个挂载点,再在上面覆盖一个可读写的容器层,只能在可读写层进行文件修改。写时复制配合分层机制减少了镜像对磁盘空间的占用和容器启动时间。
1.3.内容寻址
内容寻址存储(content-addressable storage)机制,即根据文件内容来索引镜像和镜像层。每个镜像层对应一个唯一的内容哈希值,基于哈希值来索引镜像层。对于来自不同构建的镜像层,只要拥有相同的内容哈希,也能被不同的镜像共享。
1.4.联合挂载
联合挂载技术可以在一个挂载点同时挂载多个文件系统,将挂载点的原目录与被挂载内容进行整合,使得最终可见的文件系统将会包含整合后的各层的文件和目录。是下层存储驱动(如aufs、overlay等)实现分层合并的方式。
2.镜像关键概念
registry是repository的集合,repository是镜像的集合。
manifest(描述文件)主要存在于registry中作为Docker镜像的元数据文件。在镜像被pull或load到宿主机时,manifest被转化为本地的镜像配置文件config。
Docker利用rootfs中的diff_id计算出内容寻址的索引(chainID)来获取layer相关信息。
Docker镜像管理中的layer主要存放了镜像层的diff_id、size、cache-id和parent等内容,实际的文件内容则由存储驱动来管理,并通过cache-id在本地索引到。
定义Docker镜像时,使用DSL语法来编写Dockerfile文件,每条指令描述了构建镜像的步骤。
3.镜像的分发方法
在某台机器伤导出一个Docker容器并在另一台机器上导入,可通过docker export和docker import来实现。
分发方法有docker pull和docker push、或docker save和docker load。
不同的是,docker push通过线上Docker Hub的方式迁移,而docker save则是通过线下包分发的方式迁移。