当前位置: 首页 > 编程笔记 >

Docker 制作镜像Dockerfile和commit操作

夹谷烨赫
2023-03-14
本文向大家介绍Docker 制作镜像Dockerfile和commit操作,包括了Docker 制作镜像Dockerfile和commit操作的使用技巧和注意事项,需要的朋友参考一下

构建镜像

构建镜像主要有两种方式:

使用docker commit命令从运行中的容器提交为镜像;

使用docker build命令从 Dockerfile 构建镜像。

首先介绍下如何从运行中的容器提交为镜像。我依旧使用 busybox 镜像举例,使用以下命令创建一个名为 busybox 的容器并进入 busybox 容器。

$ docker run --rm --name=busybox -it busybox sh

执行完上面的命令后,当前窗口会启动一个 busybox 容器并且进入容器中。在容器中,执行以下命令创建一个文件并写入内容:

/ # touch hello.txt && echo "I love Docker. " > hello.txt

此时在容器的根目录下,已经创建了一个 hello.txt 文件,并写入了 "I love Docker. "。

下面,我们新打开另一个命令行窗口,运行以下命令提交镜像:

$ docker commit busybox busybox:hello

sha256:cbc6406aaef080d1dd3087d4ea1e6c6c9915ee0ee0f5dd9e0a90b03e2215e81c

然后使用上面讲到的docker image ls命令查看镜像:

$ docker image ls busybox
REPOSITORY     TAG         IMAGE ID      CREATED       SIZE
busybox       hello        cbc6406aaef0    2 minutes ago    1.22MB
busybox       latest       018c9d7b792b    4 weeks ago     1.22MB

此时我们可以看到主机上新生成了 busybox:hello 这个镜像。

通过对比显然使用Dockerfile的docker build更好。docker commit的缺点如下:

需要在容器内操作麻烦,效率低。

这一点也是最重要的,其他人或者过一段时间后自己也不知道这个镜像是怎么做出来的,但是使用Dockerfile构建的镜像,我们看到是执行了apt-get install命令。

第二种方式是最重要也是最常用的镜像构建方式:Dockerfile。Dockerfile 是一个包含了用户所有构建命令的文本。通过docker build命令可以从 Dockerfile 生成镜像。

使用 Dockerfile 构建镜像具有以下特性:

Dockerfile 的每一行命令都会生成一个独立的镜像层,并且拥有唯一的 ID

Dockerfile 的命令是完全透明的,通过查看 Dockerfile 的内容,就可以知道镜像是如何一步步构建的

Dockerfile 是纯文本的,方便跟随代码一起存放在代码仓库并做版本管理

看到使用 Dockerfile 的方式构建镜像有这么多好的特性,你是不是已经迫不及待想知道如何使用了。别着急,我们先学习下 Dockerfile 常用的指令。

Dockerfile 指令 指令简介
FROM Dockerfile 除了注释第一行必须是 FROM ,FROM 后面跟镜像名称,代表我们要基于哪个基础镜像构建我们的容器。
RUN RUN 后面跟一个具体的命令,类似于 Linux 命令行执行命令。
ADD 拷贝本机文件或者远程文件到镜像内
COPY 拷贝本机文件到镜像内
USER 指定容器启动的用户
ENTRYPOINT 容器的启动命令
CMD CMD 为 ENTRYPOINT 指令提供默认参数,也可以单独使用 CMD 指定容器启动参数
ENV 指定容器运行时的环境变量,格式为 key=value
ARG 定义外部变量,构建镜像时可以使用 build-arg = 的格式传递参数用于构建
EXPOSE 指定容器监听的端口,格式为 [port]/tcp 或者 [port]/udp
WORKDIR 为 Dockerfile 中跟在其后的所有 RUN、CMD、ENTRYPOINT、COPY 和 ADD 命令设置工作目录。

看了这么多指令,感觉有点懵?别担心,我通过一个实例让你来熟悉它们。这是一个 Dockerfile:

FROM centos:7 
COPY nginx.repo /etc/yum.repos.d/nginx.repo 
RUN yum install -y nginx 
EXPOSE 80 
ENV HOST=mynginx 
CMD ["nginx","-g","daemon off;"]

第一行表示我要基于 centos:7 这个镜像来构建自定义镜像。这里需要注意,每个 Dockerfile 的第一行除了注释都必须以 FROM 开头。

第二行表示拷贝本地文件 nginx.repo 文件到容器内的 /etc/yum.repos.d 目录下。这里拷贝 nginx.repo 文件是为了添加 nginx 的安装源。

第三行表示在容器内运行yum install -y nginx命令,安装 nginx 服务到容器内,执行完第三行命令,容器内的 nginx 已经安装完成。

第四行html" target="_blank">声明容器内业务(nginx)使用 80 端口对外提供服务。

第五行定义容器启动时的环境变量 HOST=mynginx,容器启动后可以获取到环境变量 HOST 的值为 mynginx。

第六行定义容器的启动命令,命令格式为 json 数组。这里设置了容器的启动命令为 nginx ,并且添加了 nginx 的启动参数 -g 'daemon off;' ,使得 nginx 以前台的方式启动。

镜像的实现原理

其实 Docker 镜像是由一系列镜像层(layer)组成的,每一层代表了镜像构建过程中的一次提交。下面以一个镜像构建的 Dockerfile 来说明镜像是如何分层的。

FROM busybox

COPY test /tmp/test

RUN mkdir /tmp/testdir

上面的 Dockerfile 由三步组成:

第一行基于 busybox 创建一个镜像层;

第二行拷贝本机 test 文件到镜像内;

第三行在 /tmp 文件夹下创建一个目录 testdir。

这里我的 Docker 使用的是 overlay2 文件驱动,进入到/var/lib/docker/overlay2目录下使用tree .命令查看产生的镜像文件:

$ tree .
 
# 以下为 tree . 命令输出内容
 
|-- 3e89b959f921227acab94f5ab4524252ae0a829ff8a3687178e3aca56d605679
 
|  |-- diff # 这一层为基础层,对应上述 Dockerfile 第一行,包含 busybox 镜像所有文件内容,例如 /etc,/bin,/var 等目录
 
... 此次省略部分原始镜像文件内容
 
|  `-- link 
 
|-- 6591d4e47eb2488e6297a0a07a2439f550cdb22845b6d2ddb1be2466ae7a9391
 
|  |-- diff  # 这一层对应上述 Dockerfile 第二行,拷贝 test 文件到 /tmp 文件夹下,因此 diff 文件夹下有了 /tmp/test 文件
 
|  |  `-- tmp
 
|  |    `-- test
 
|  |-- link
 
|  |-- lower
 
|  `-- work
 
|-- backingFsBlockDev
 
|-- bec6a018080f7b808565728dee8447b9e86b3093b16ad5e6a1ac3976528a8bb1
 
|  |-- diff # 这一层对应上述 Dockerfile 第三行,在 /tmp 文件夹下创建 testdir 文件夹,因此 diff 文件夹下有了 /tmp/testdir 文件夹
 
|  |  `-- tmp
 
|  |    `-- testdir
 
|  |-- link
 
|  |-- lower
 
|  `-- work
 
...

通过上面的目录结构可以看到,Dockerfile 的每一行命令,都生成了一个镜像层,每一层的 diff 夹下只存放了增量数据,如图 2 所示。

分层的结构使得 Docker 镜像非常轻量,每一层根据镜像的内容都有一个唯一的 ID 值,当不同的镜像之间有相同的镜像层时,便可以实现不同的镜像之间共享镜像层的效果。

总结一下, Docker 镜像是静态的分层管理的文件组合,镜像底层的实现依赖于联合文件系统(UnionFS)。充分掌握镜像的原理,可以帮助我们在生产实践中构建出最优的镜像,同时也可以帮助我们更好地理解容器和镜像的关系。

总结

到此,相信你已经对 Docker 镜像这一核心概念有了较深的了解,并熟悉了 Docker 镜像的常用操作(拉取、查看、“重命名”、删除和构建自定义镜像)及底层实现原理。

镜像操作命令:

拉取镜像,使用 docker pull 命令拉取远程仓库的镜像到本地 ;

重命名镜像,使用 docker tag 命令“重命名”镜像 ;

查看镜像,使用 docker image ls 或 docker images 命令查看本地已经存在的镜像;

删除镜像,使用 docker rmi 命令删除无用镜像 ;

构建镜像,构建镜像有两种方式。第一种方式是使用 docker build 命令基于 Dockerfile 构建镜像,也是我比较推荐的镜像构建方式;第二种方式是使用 docker commit 命令基于已经运行的容器提交为镜像。

镜像的实现原理:

镜像是由一系列的镜像层(layer )组成,每一层代表了镜像构建过程中的一次提交,当我们需要修改镜像内的某个文件时,只需要在当前镜像层的基础上新建一个镜像层,并且只存放修改过的文件内容。分层结构使得镜像间共享镜像层变得非常简单和方便。

以上这篇Docker 制作镜像Dockerfile和commit操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持小牛知识库。

 类似资料:
  • 本文向大家介绍Docker Dockerfile 定制镜像的方法,包括了Docker Dockerfile 定制镜像的方法的使用技巧和注意事项,需要的朋友参考一下 使用 Dockerfile 定制镜像 镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么无法重复的问题、镜像构建透明性的问题、体积的问题就都

  • 从前面一节的docker commit的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件等信息,但是命令毕竟只是命令,每次定制都得去重复执行这个命令,而且还不够直观,如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么这些问题不就都可以解决了吗?对的,这个脚本就是我们说的Dockerfile。 介绍 Dockerfile 是一个文

  • 这是我编写的Dockerfile文件,但是构建镜像的时候发现没有执行npm install,自然也不会有dist文件,不知道是哪里写的有问题,请教一下大家

  • 使用 Dockerfile 定制镜像 从刚才的 docker commit 的学习中,我们可以了解到,镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。 Dockerfile 是一个文本文件,其内包

  • 本文向大家介绍Docker镜像压缩与优化操作,包括了Docker镜像压缩与优化操作的使用技巧和注意事项,需要的朋友参考一下 现如今docker如此受人追捧,主要是因为它的轻量化、可以快速部署以及资源的利用。但是一个docker images质量的好与坏,主要取决于Dockerfile编写的质量。同样功能的镜像,但是不同的Dockerfile build出来的镜像大小是不一样的,这是因为docker

  • 介绍基于标准ISO镜像制作全平台通用的虚拟机镜像。 云联壹云 镜像市场提供部分提前制作好的虚拟机镜像,如镜像市场中的镜像不满足需求或用户有自定义设置镜像的需求,可通过本章节制作镜像。 镜像制作流程 提前准备好标准ISO镜像,支持用户从镜像市场-ISO界面导入或直接上传ISO镜像。 在虚拟机列表中新建虚拟机,选择“从ISO启动”并选择对应的ISO镜像,创建成功后,并通过VNC终端进行按照界面提示安装