docker(13):docker镜像的分层
docker(13):docker镜像的分层
https://www.cnblogs.com/CloudMan6/p/6806193.html
https://docs.docker.com/storage/storagedriver/
https://www.jianshu.com/p/e3a4b69f649c
1 什么是镜像分层
因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在 Docker 设计时,就充分利用 Union FS 的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个 ISO 那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件系统联合组成。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除前一层的文件,而是仅在当前层标记为该文件已删除。在最终容器运行的时候,虽然不会看到这个文件,但是实际上该文件会一直跟随镜像。因此,在构建镜像的时候,需要额外小心,每一层尽量只包含该层需要添加的东西,任何额外的东西应该在该层构建结束前清理掉。
分层存储的特征还使得镜像的复用、定制变的更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
1.1 图形
① 新镜像不再是从 scratch 开始,而是直接在 Debian base 镜像上构建。
② 安装 emacs 编辑器。
③ 安装 apache2。
④ 容器启动时运行 bash。
一个docker镜像由多个可读的镜像层组成,然后运行的容器会在这个docker的镜像上面多加一层可写的容器层,任何的对文件的更改都只存在此容器层。因此任何对容器的操作均不会影响到镜像。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。
只有容器层是可写的,容器层下面的所有镜像层都是只读的。
下面我们深入讨论容器层的细节。
镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。
- 添加文件 在容器中创建文件时,新文件被添加到容器层中。
- 读取文件 在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。
- 修改文件 在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
- 删除文件 在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。
只有当需要修改时才复制一份数据,这种特性被称作 Copy-on-Write。可见,容器层保存的是镜像变化的部分,不会对镜像本身进行任何修改。
这样就解释了我们前面提出的问题:容器层记录对镜像的修改,所有镜像层都是只读的,不会被容器修改,所以镜像可以被多个容器共享。
1.2 命令呈现
[root@docker-136 ~]# docker images | grep kod kod v8 58de0c0137bb 20 hours ago 556MB kod v7 e36f3f496d0a 20 hours ago 556MB kod v1 681c97c0548e 25 hours ago 550MB [root@docker-136 ~]# docker image history kod:v8 IMAGE CREATED CREATED BY SIZE COMMENT 58de0c0137bb 20 hours ago /bin/sh -c #(nop) CMD ["/bin/bash" "/init.s… 0B 0fa6d928d688 20 hours ago /bin/sh -c #(nop) ADD file:fa11fc6a3c3a33648… 47B 7a19cf169c31 20 hours ago /bin/sh -c chown -R nginx:nginx /usr/share/… 46.2MB 72fd74170a7a 20 hours ago /bin/sh -c cd /usr/share/nginx/html && \cur… 46.2MB 1271f8a62000 20 hours ago /bin/sh -c #(nop) ADD file:01f739a3567b5c1f4… 653B e75650fe8ed5 20 hours ago /bin/sh -c rm -f /etc/nginx/nginx.conf 0B 625b5155b66c 20 hours ago /bin/sh -c sed -i "s#apache#nginx#g" /etc/p… 10kB db621c02d365 20 hours ago /bin/sh -c yum install curl nginx net-tools… 262MB 0fc4bba9b2ac 20 hours ago /bin/sh -c curl -o /etc/yum.repos.d/epel.rep… 664B caa065f6c677 20 hours ago /bin/sh -c sed -i 's#$basearch#x86_64#g' /et… 1.44kB 4c9370a41440 20 hours ago /bin/sh -c sed -i 's#$releasever#7#g' /etc/y… 1.46kB 78d6598368d1 20 hours ago /bin/sh -c curl -o /etc/yum.repos.d/CentOS-B… 1.57kB 9a247db207e6 4 days ago /bin/sh -c #(nop) ENV container=docker 0B 9f38484d220f 5 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 5 months ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 5 months ago /bin/sh -c #(nop) ADD file:074f2c974463ab38c… 202MB [root@docker-136 ~]#
2 镜像分层的好处
共享资源,节省资源
有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份
base 镜像;同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了
修改dockerfile之后(尽量追加到文件后面),再次构建速度快。