为了有效地利用存储驱动程序,了解Docker如何构建和存储镜像以及如何使用这些镜像非常重要。

镜像分层

Docker镜像是由一系列层来构成的,每层代表Dockerfile中的一条指令,依下面Dockerfile为例:

FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py

Dockerfile包含四个命令,每个命令都会新创建一个层。FROM语句会从ubuntu:18.04镜像创建一个层。COPY指令会从Docker客户端的当前目录下添加一些文件。RUN指令使用了make指令来构建。最后CMD是☞在容器中运行什么命令。

而对于Docker来说,创建新容器时,每一层都会彼此堆叠,可以在基础层的基础上添加新的可写容器层。对容器的所做的所有更改都将写入到该可写容器层中。下图显示了基于Ubuntu 15.04 的容器。对于Image layers都是Read Only的。

容器和层

对于容器和镜像(containerimage)的主要区别就是顶部的可写层(the top writable layer),在容器中添加数据或者修改现有数据的所有读写操作都会存储在此可写层中。删除容器后,可写层也会被删除,而基础镜像则保持不变。

每个容器都会有自己的可写层,所有的改变都存储在该容器层中。多个容器可以共享对同一基础镜像的访问,但可以拥有自己的数据状态。

如果需要对完全相同的数据的访问权限,需要将该数据存储在Docker volume中并且装入到容器中。

Copy-on-write策略

写时复制是一种共享和复制文件的策略,可以最大程度地提高效率。

当我们使用dockerpull`指令时会从仓库拉下一个镜像例如下面的例子

$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
f476d66f5408: Pull complete
8882c27f669e: Pull complete
d9af21273955: Pull complete
f5029279ec12: Pull complete
Digest: sha256:ab6cb8de3ad7bb33e2534677f865008535427390b117d7939193f8d1a6613e34
Status: Downloaded newer image for ubuntu:18.04

所有的这些层都会在Docker主机本地存储区域内存储,可以通过以下指令来列出

$ ls /var/lib/docker/overlay2
16802227a96c24dcbeab5b37821e2b67a9f921749cd9a2e386d5a6d5bc6fc6d3
377d73dbb466e0bc7c9ee23166771b35ebdbe02ef17753d79fd3571d4ce659d7
3f02d96212b03e3383160d31d7c6aeca750d2d8a1879965b89fe8146594c453d
ec1ec45792908e90484f7e629330666e7eee599f08729c93890a7205a6ba35f5
l

依下面的Dockerfile为例,创建一个名为acme/my-base-image:1.0的镜像。

FROM ubuntu:18.04
COPY . /app

第二个Dockerfile依第一个Dockerfile为例,但是有用一个增加的层。

FROM acme/my-base-image:1.0
CMD /app/hello.sh

第二个镜像包含第一个镜像的所有层,再加上带有CMD指令的新层,以及一个可读写的容器层。因为Docker已经拥有第一个镜像的所有层,所以不需要再次将其pull下来。

构建这两个Dockerfile镜像,可以通过docker historydocker image ls指令来验证共享层的加密ID是否相同。

  1. 创建一个新文件夹cow-test/,并切换到该目录下。
  2. cow-test/目录下,创建一个名为hello.sh的文件内容如下:
#!/bin/sh
echo "Hello world"

然后设置可执行

chmod +x hello.sh

  1. 将上面第一个镜像复制为Dockerfile.base
  2. 将上面第二个镜像复制为Dockerfile
  3. cow-test/目录下,构建第一个镜像
$ docker build -t acme/my-base-image:1.0 -f Dockerfile.base .
Sending build context to Docker daemon  812.4MB
Step 1/2 : FROM ubuntu:18.04
---> d131e0fa2585
Step 2/2 : COPY . /app
---> Using cache
---> bd09118bcef6
Successfully built bd09118bcef6
Successfully tagged acme/my-base-image:1.0

  1. 构建第二个镜像
$ docker build -t acme/my-final-image:1.0 -f Dockerfile .Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM acme/my-base-image:1.0
---> bd09118bcef6
Step 2/2 : CMD /app/hello.sh
---> Running in a07b694759ba
---> dbf995fc07ff
Removing intermediate container a07b694759ba
Successfully built dbf995fc07ff
Successfully tagged acme/my-final-image:1.0

  1. 查看镜像的大小。
$ docker image lsREPOSITORY                         TAG                     IMAGE ID            CREATED             SIZE
acme/my-final-image                1.0                     dbf995fc07ff        58 seconds ago      103MB
acme/my-base-image                 1.0                     bd09118bcef6        3 minutes ago       103MB

  1. 查看每个镜像中层的大小
$ docker history bd09118bcef6
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
bd09118bcef6        4 minutes ago       /bin/sh -c #(nop) COPY dir:35a7eb158c1504e...   100B
d131e0fa2585        3 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           3 months ago        /bin/sh -c mkdir -p /run/systemd && echo '...   7B
<missing>           3 months ago        /bin/sh -c sed -i 's/^#s*(deb.*universe...   2.78kB
<missing>           3 months ago        /bin/sh -c rm -rf /var/lib/apt/lists/*          0B
<missing>           3 months ago        /bin/sh -c set -xe   && echo '#!/bin/sh' >...   745B
<missing>           3 months ago        /bin/sh -c #(nop) ADD file:eef57983bd66e3a...   103MB$ docker history dbf995fc07ffIMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
dbf995fc07ff        3 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/sh" "-c" "/a...   0B
bd09118bcef6        5 minutes ago       /bin/sh -c #(nop) COPY dir:35a7eb158c1504e...   100B
d131e0fa2585        3 months ago        /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           3 months ago        /bin/sh -c mkdir -p /run/systemd && echo '...   7B
<missing>           3 months ago        /bin/sh -c sed -i 's/^#s*(deb.*universe...   2.78kB
<missing>           3 months ago        /bin/sh -c rm -rf /var/lib/apt/lists/*          0B
<missing>           3 months ago        /bin/sh -c set -xe   && echo '#!/bin/sh' >...   745B
<missing>           3 months ago        /bin/sh -c #(nop) ADD file:eef57983bd66e3a...   103MB

可以看到除了第二个镜像的顶层以外,所有层都是相同的,其他层在这两个镜像中共享,并且只会在/var/lib/docker目录中存储一次,实际上新层并不会占用任何空间,因为它只是运行命令。

磁盘上容器的大小

可以使用docker ps -s指令来查看容器的大小。

  • size表示每个容器的可写层使用的大小。
  • virtual size表示容器使用的用于只读镜像的数据的数据量加上容器可写层的大小。多个容器可以共享一些或者所有的只读镜像数据。

因此每个正在运行的容器所使用磁盘总空间大小是virtual sizesize的某种组合。如果多个容器从相同的基础镜像开始,所以这些容器在磁盘上的总大小为所有容器的大小sizeSUM of all container size)加上一个镜像的大小(virtual size-size)

本文简单介绍了docker镜像分层。

  • 镜像如果共享了相同的层只会在/var/lib/docker下存储一个,通过这个可以大大减少容器编译、推送的时长。

docker 镜像_Docker镜像分层相关推荐

  1. 系统制成docker镜像_docker镜像原理 镜像制作 dockerfile

    为什么一个centos镜像只有两百多兆,而tomcat镜像五百多兆 1.先说说操作系统 操作系统组成部分: 进程调度子系统 进程通信子系统 内存管理子系统 设备管理子系统 文件管理子系统 网络通信子系 ...

  2. docker看远程仓库镜像_Docker 镜像使用

    Docker 镜像使用 当运行容器时,使用的镜像如果在本地中不存在,docker 就会自动从 docker 镜像仓库中下载,默认是从 Docker Hub 公共镜像源下载. 下面我们来学习: 1.管理 ...

  3. docker 镜像重命名_Docker 镜像该怎么传

    开门见山,提一个问题,如何把一个容器从开发环境取出来,到其他机器上跑起来?docker hub是一个很好的选择,把镜像提交上去,到另外的机器上拉取下来,很方便. 但是,没有网络怎么办,本文告诉你如何操 ...

  4. docker 删除所有未启动的容器_Docker 镜像容器常用操作(让我们用 docker 溜得飞起)...

    推荐阅读: 面试字节跳动三轮凉凉,内推4面终拿下抖音offer(Java后台研发)​zhuanlan.zhihu.com 一线架构师Spring boot 学习笔记:我的成长全记在这份PDF文档里​z ...

  5. 【docker教程】docker视频教程(ubuntu)数据卷挂载、数据卷容器volume、端口映射(镜像叠加,分层复用)rootfs、bootfs(没看完)

    黑马程序员Docker容器化技术,从零学会Docker教程 可以先看1-13课.以及 docker概述 文章目录 docker概述 ubuntu安装docker docker架构 配置docker镜像 ...

  6. docker 打包新镜像原有配置丢失_Docker简介与安装

    Docker简介:Docker与虚拟机区别:Docker的优点及内部组件说明:如何安装Docker与镜像加速配置. 什么是Docker Docker提供了一个可以运行你的应用程序的封装,或者说容器.它 ...

  7. docker build命令详解_Docker镜像与容器常用命令图文详解

    一.系统命令 #查看docker版本 docker version #查看docker的系统信息,包含镜像容器的数量 docker info #查看docker的所有命令 docker --help ...

  8. docker from指令的含义_Docker 镜像常用命令

    获取镜像 从 Docker 镜像仓库获取镜像的命令是 docker pull.其命令格式为: docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签] ...

  9. docker 删除包含关键字的镜像_Docker 架构及工作原理

    通过下图可以得知,Docker 在运行时分为 Docker 引擎(服务端守护进程) 和 客户端工具,我们日常使用各种 docker 命令,其实就是在使用 客户端工具 与 Docker 引擎 进行交互. ...

最新文章

  1. Nandflash K9F1208U0B学习
  2. SEO日暮途穷?做好几点实现华丽蜕变
  3. 大数据WEB阶段Spring框架(三)声明式事务处理
  4. 多核编程文章汇总[z]
  5. android 评论的展开功能,Android开发实现ListView点击展开收起效果示例
  6. 数据中心生成器行业调研报告 - 市场现状分析与发展前景预测
  7. 热传导方程以及Matlab求解
  8. android 创建线程的三种方式
  9. C语言 同构数的算法
  10. 网页页面缩小放大的快捷键
  11. [转]FastDb介绍
  12. b站上的计算机课程有哪些,B站课程排行榜,这届大学生最爱学什么?
  13. Banner大小之国际标准
  14. android pie mi 3 tab,前沿科技:三星Galaxy Tab S3和Tab A(2017)正在获得Android 9.0 Pie更新
  15. android app 运行时提示 应用专为旧版 Android 打造
  16. 根据微信的code_url 给前端返回二维码图片--转换成base
  17. JavaScript期末大作业 罗兰永恒花园动漫价绍网页 7页,含有table表格,js表单验证还有首页视频
  18. 纪中GMOJ语言模块题目1009
  19. 树形表格TreeGrid
  20. FCPX插件:专业分级调色插件ColorFinale Pro

热门文章

  1. C语言图形化编程 【二】
  2. MySQL带关系运算符的查询
  3. 【JUC并发编程04】线程间定制化通信(单标志法存在的问题)
  4. 【Python】【应用 01】使用python初步处理文件数据就那么简单!(本文以处理excel和目录为例)
  5. CTO:再写if-else,逮着一个罚款1000!
  6. String类split方法
  7. 前后台分离使用cookie判断用户状态以及传递参数
  8. 爬取虎牙之三:通过json数据获取所有直播情况
  9. 双指针算法(三):力扣【167.两数之和 | 经典例题
  10. 利用cookie显示上次浏览的时间