Docker 镜像的构建原理和方式

Docker构建镜像的方式有多种,先介绍下最常用的两种

  • 通过docker commit命令,基于一个已存在的容器构建出镜像。
  • 编写 Dockerfile 文件,并使用docker build命令来构建镜像。

上面这两种方法中,镜像构建的底层原理是相同的,都是通过下面 3 个步骤来构建镜像:

  • 基于原镜像,启动一个 Docker 容器。在容器中进行一些操作,例如执行命令、安装文件等。
  • 由这些操作产生的文件变更都会被记录在容器的存储层中。
  • 将容器存储层的变更 commit 到新的镜像层中,并添加到原镜像上。

下面,具体了解这两种构建 Docker 镜像的方式。

通过docker commit命令,基于一个已存在的容器构建出镜像

通过docker commit来构建一个镜像,命令的格式为docker commit [选项] [<仓库名>[:<标签>]]。

具体步骤如下:

  1. 执行docker ps获取需要构建镜像的容器 ID 08cd43c7e50d
  2. 执行docker pause 08cd43c7e50d暂停08cd43c7e50d容器的运行。
  3. 执行docker commit 08cd43c7e50d redis:test,基于容器 ID 08cd43c7e50d构建 Docker 镜像。
  4. 执行docker images redis:test,查看镜像是否成功构建。

这种镜像构建方式通常用在下面两个场景中:

  • 构建临时的测试镜像;
  • 容器被入侵后,使用docker commit,基于被入侵的容器构建镜像,从而保留现场,方便以后追溯。

除了这两种场景,不建议你使用docker commit来构建生产现网环境的镜像。
主要原因有两个:

  1. 使用docker commit构建的镜像包含了编译构建、安装软件,以及程序运行产生的大量无用文件,这会导致镜像体积很大,非常臃肿。
  2. 使用docker commit构建的镜像会丢失掉所有对该镜像的操作历史,无法还原镜像的构建过程,不利于镜像的维护。

编写 Dockerfile 文件,并使用docker build命令来构建镜像

docker build命令会读取Dockerfile的内容,并将Dockerfile的内容发送给 Docker 引擎,最终 Docker 引擎会解析Dockerfile中的每一条指令,构建出需要的镜像。

docker build的命令格式为docker build [OPTIONS] PATH | URL | -。PATH、URL、-指出了构建镜像的上下文(context),context 中包含了构建镜像需要的Dockerfile文件和其他文件。默认情况下,Docker 构建引擎会查找 context 中名为Dockerfile的文件,但你可以通过-f, --file选项,手动指定Dockerfile文件。例如:

 $ docker build -f Dockerfile -t redis:test .

使用 Dockerfile 构建镜像,本质上也是通过镜像创建容器,并在容器中执行相应的指令,然后停止容器,提交存储层的文件变更。和用docker commit构建镜像的方式相比,它有三个好处:

  • Dockerfile 包含了镜像制作的完整操作流程,其他开发者可以通过 Dockerfile 了解并复现制作过程。
  • Dockerfile 中的每一条指令都会创建新的镜像层,这些镜像可以被 Docker Daemnon 缓存。再次制作镜像时,Docker 会尽量复用缓存的镜像层(using cache),而不是重新逐层构建,这样可以节省时间和磁盘空间。
  • Dockerfile 的操作流程可以通过docker image history [镜像名称]查询,方便开发者查看变更记录。

执行docker build后的构建流程为:

  • 第一步,docker build会将 context 中的文件打包传给 Docker daemon。如果 context 中有.dockerignore文件,则会从上传列表中删除满足.dockerignore规则的文件。

这里有个例外,如果.dockerignore文件中有.dockerignore或者Dockerfiledocker build命令在排除文件时会忽略掉这两个文件。如果指定了镜像的 tag,还会对 repository 和 tag 进行验证。

  • 第二步,docker build命令向 Docker server 发送 HTTP 请求,请求 Docker server 构建镜像,请求中包含了需要的 context 信息。
  • 第三步,Docker server 接收到构建请求之后,会执行以下流程来构建镜像:
  1. 创建一个临时目录,并将 context 中的文件解压到该目录下。
  2. 读取并解析 Dockerfile,遍历其中的指令,根据命令类型分发到不同的模块去执行。
  3. Docker 构建引擎为每一条指令创建一个临时容器,在临时容器中执行指令,然后 commit 容器,生成一个新的镜像层。
  4. 最后,将所有指令构建出的镜像层合并,形成 build 的最后结果。最后一次 commit 生成的镜像 ID 就是最终的镜像 ID。

为了提高构建效率,docker build默认会缓存已有的镜像层。如果构建镜像时发现某个镜像层已经被缓存,就会直接使用该缓存镜像,而不用重新构建。如果不希望使用缓存的镜像,可以在执行docker build命令时,指定--no-cache=true参数。

Docker 匹配缓存镜像的规则为:遍历缓存中的基础镜像及其子镜像,检查这些镜像的构建指令是否和当前指令完全一致,如果不一样,则说明缓存不匹配。对于ADDCOPY指令,还会根据文件的校验和(checksum)来判断添加到镜像中的文件是否相同,如果不相同,则说明缓存不匹配。

这里要注意,缓存匹配检查不会检查容器中的文件。比如,当使用RUN apt-get -y update命令更新了容器中的文件时,缓存策略并不会检查这些文件,来判断缓存是否匹配。

最后,可以通过docker history命令来查看镜像的构建历史,如下图所示:

通过docker save和docker load命令构建

docker save用来将镜像保存为一个 tar 文件,docker load用来将 tar 格式的镜像文件加载到当前机器上,例如:

# 在 A 机器上执行,并将 nginx-v1.0.0.tar.gz 复制到 B 机器
$ docker save nginx | gzip > nginx-v1.0.0.tar.gz# 在 B 机器上执行
$ docker load -i nginx-v1.0.0.tar.gz

通过上面的命令,我们就在机器 B 上创建了nginx镜像。

通过docker export和docker import命令构建

通过docker export 保存镜像,再通过docker import 加载镜像,具体命令如下:

# 在 A 机器上执行,并将 nginx-v1.0.0.tar.gz 复制到 B 机器
$ docker export nginx > nginx-v1.0.0.tar.gz# 在 B 机器上执行
$ docker import - nginx:v1.0.0 nginx-v1.0.0.tar.gz

通过docker export导出的镜像和通过docker save保存的镜像相比,会丢失掉所有的镜像构建历史。在实际生产环境中,我不建议你通过docker save和docker export这两种方式来创建镜像。

较推荐的方式是:在 A 机器上将镜像 push 到镜像仓库,在 B 机器上从镜像仓库 pull 该镜像。

Docker 四种制作镜像方式相关推荐

  1. Jenkins的四种安装部署方式以及Jenkins的基本配置与基本使用

    Jenkins的四种安装部署方式以及Jenkins的基本配置与基本使用 安装Jenkins 1.yum安装Jenkins 下载与安装 修改配置 修改默认端口 2.基于War包的形式部署Jenkins ...

  2. Docker Compose搭建consul群集环境(了解Docker Compose及常用命令,Docker四种网络,Doker指定端口)

    文章目录 Docker Compose搭建consul群集环境 认识Docker Compose IConsul Docker Compose容器编排 Dasker Compose配置常用字段 Bos ...

  3. 爆破专栏丨Spring Security系列教程之Spring Security的四种权限控制方式

    原创:一一哥 前言: 在前面的章节中,一一哥 已经给大家介绍了Spring Security的很多功能,在这些众多功能中,我们知道其核心功能其实就是认证+授权. 在前面我们分别基于内存模型.基于默认的 ...

  4. HIVE的安装配置、mysql的安装、hive创建表、创建分区、修改表等内容、hive beeline使用、HIVE的四种数据导入方式、使用Java代码执行hive的sql命令

    1.上传tar包 这里我上传的是apache-hive-1.2.1-bin.tar.gz 2.解压 mkdir -p /home/tuzq/software/hive/ tar -zxvf apach ...

  5. java按钮权限控制_详解Spring Security 中的四种权限控制方式

    Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Se ...

  6. ASP.NET MVC下的四种验证编程方式[续篇]

    ASP.NET MVC下的四种验证编程方式[续篇] 原文:ASP.NET MVC下的四种验证编程方式[续篇] 在<ASP.NET MVC下的四种验证编程方式>一文中我们介绍了ASP.NET ...

  7. java 按钮 监听_Button的四种监听方式

    Button按钮设置点击的四种监听方式 注:加粗放大的都是改变的代码 1.使用匿名内部类的形式进行设置 使用匿名内部类的形式,直接将需要设置的onClickListener接口对象初始化,内部的onC ...

  8. python接口自动化(十)--post请求四种传送正文方式(详解)

    简介 post请求我在python接口自动化(八)–发送post请求的接口(详解)已经讲过一部分了,主要是发送一些较长的数据,还有就是数据比较安全等.我们要知道post请求四种传送正文方式首先需要先了 ...

  9. 计算机图片怎么截图快捷键,电脑截图快捷键四种截屏方式,笔记本电脑如何截屏截图?...

    电脑截图快捷键四种截屏方式,笔记本电脑如何截屏截图? 网际百科资讯    知识宝库    2020-3-18    43955    0评论 电脑截图快捷键四种截屏方式,笔记本电脑如何截屏截图?给你推 ...

最新文章

  1. 弹出窗口以及关闭窗口
  2. 无需任何标记数据,几张照片就能还原出3D物体结构,自监督学习还能这样用...
  3. php对提交数据的验证
  4. CUMCM:05B  DVD在线租赁
  5. 2021年中国在线旅游行业分析报告
  6. keras添加正则化全连接_第16章 Keras使用Dropout正则化防止过拟合
  7. 从零开始学Pytorch之数据操作
  8. 我的PGA我作主----搞清楚什么是真正的PGA
  9. 关于Myeclipse自带JDK与本机安装JDK的的区别
  10. cfa考试用计算机,cfa考试一定要用专用计算器么
  11. android 查看cad方案,安卓手机可以CAD看图吗?怎么查看接收的CAD图纸文件?
  12. 浩辰云建筑2021功能详细介绍
  13. matlab与信道编码,基于MATLAB的信道编码.doc
  14. WIN下静默安装MSI文件
  15. wamp mysql_WampServer 下载以及安装问题 以及配置远程连接MYSQL
  16. html中制作banner,css banner轮播图怎么做?
  17. Python多线程编程详解,文章比较长,需耐心浏览
  18. pumping lemma 泵引理
  19. SparkRDD函数详解
  20. 小苹果蹿红背后的网络营销思考

热门文章

  1. 情绪管理本质上是认知管理 —— 一份情绪、认知管理升级清单
  2. 百付宝携手瑞星 打造零风险支付平台
  3. 计算机关于组建网络的工作,局域网组建方法_怎么建立局域网_局域网基础知识...
  4. 怎样把iPhoneX手机备忘录同步到华为p20手机上?
  5. 编辑PDF的多级书签
  6. Java 全集(上)
  7. 在python中数据的输出用哪个函数名_在Python中,数据的输出用哪个函数名
  8. COM编程之三 QueryInterface
  9. [opencv] 练习题实现 使用轨迹栏创建颜色和画笔半径可调的Paint应用程序。有关绘制的信息,请参阅有关鼠标处理的先前教程。
  10. 华为OD机试真题Java实现【密室逃生游戏】真题+解题思路+代码(20222023)