Docker制作镜像的两种实现方式

 更新时间:2023年07月05日 11:04:43   作者:_wei丶  
本文主要介绍了Docker制作镜像的两种实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Docker 镜像的构建原理和方式

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

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

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

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

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

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

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

具体步骤如下:

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

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

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

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

主要原因有两个:

  • 使用docker commit构建的镜像包含了编译构建、安装软件,以及程序运行产生的大量无用文件,这会导致镜像体积很大,非常臃肿。
  • 使用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 接收到构建请求之后,会执行以下流程来构建镜像:

  • 创建一个临时目录,并将 context 中的文件解压到该目录下。
  • 读取并解析 Dockerfile,遍历其中的指令,根据命令类型分发到不同的模块去执行。
  • Docker 构建引擎为每一条指令创建一个临时容器,在临时容器中执行指令,然后 commit 容器,生成一个新的镜像层。
  • 最后,将所有指令构建出的镜像层合并,形成 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制作镜像的两种实现方式的文章就介绍到这了,更多相关Docker制作镜像内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解Centos7 下建立 Docker 桥接网络

    详解Centos7 下建立 Docker 桥接网络

    本篇文章主要介绍了详解Centos7 下建立 Docker 桥接网络,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • docker-compose up -d和docker-compose up --build的区别

    docker-compose up -d和docker-compose up -

    本文主要介绍了docker-compose up -d和docker-compose up --build的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Docker安装FTP服务器的方法步骤

    Docker安装FTP服务器的方法步骤

    FTP是一种传输协议,本文主要介绍了Docker安装FTP服务器的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • CentOS7 Nexus安装步骤详细介绍

    CentOS7 Nexus安装步骤详细介绍

    这篇文章主要介绍了CentOS7 Nexus安装步骤详细介绍的相关资料,这里对CentOS7 安装Nexus 进行了详细介绍,需要的朋友可以参考下
    2016-11-11
  • Docker打包前后端项目的实现示例

    Docker打包前后端项目的实现示例

    目前我们大多数服务应该会使用Docker来进行部署,本文主要介绍了Docker打包前后端项目的实现示例,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • docker 连接宿主Mysql操作

    docker 连接宿主Mysql操作

    这篇文章主要介绍了docker 连接宿主Mysql操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • docker mysql修改root账号密码并赋予权限

    docker mysql修改root账号密码并赋予权限

    本文主要介绍了docker mysql修改root账号密码并赋予权限,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • docker-compose的安装和使用详解

    docker-compose的安装和使用详解

    这篇文章主要介绍了docker-compose的安装和使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Linux中安装Docker Compose的步骤

    Linux中安装Docker Compose的步骤

    Docker Compose需要在系统上安装了Docker才能正常工作,如果你的系统上还没有安装Docker,请先安装Docker,下面给大家分享Linux中安装Docker Compose的步骤,感兴趣的朋友一起看看吧
    2024-05-05
  • 浅谈docker学习之docker数据卷(volume)

    浅谈docker学习之docker数据卷(volume)

    这篇文章主要介绍了浅谈docker学习之docker数据卷(volume),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12

最新评论