拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Dockerfile中run、cmd和entrypoint之间的区别

Dockerfile中run、cmd和entrypoint之间的区别

白鹭 - 2021-11-24 915 0 0

1.概述

在Dockerfile中,我们经常会遇到诸如runcmd,entrypoint类的指令。乍一看,它们全部用于指定和运行命令。但是它们之间有什么区别?它们如何相互影响?

在本教程中,我们将回答这些问题。我们将介绍这些说明中的每一个做什么以及它们如何工作。我们还将研究它们在构建映像和运行Docker容器中所扮演的角色。

2.设定

首先,让我们创建一个脚本log-event.sh.它只是在文件中添加一行,然后打印它:

#!/bin/sh



 echo `date` [email protected] >> log.txt;

 cat log.txt;

现在,让我们创建一个简单的Dockerfile:

FROM alpine

 ADD log-event.sh /

在不同情况下,通过将行附加到log.txt

3. run命令

当我们构建映像时,将run这意味着传递给run的命令将在新层的当前图像之上执行。然后将结果提交到图像。让我们看看它的实际效果。

首先,我们将run指令添加到我们的Dockerfile中:

FROM alpine

 ADD log-event.sh /

 RUN ["/log-event.sh", "image created"]

其次,让我们用以下内容建立我们的形象:

docker build -t myimage .

现在,我们希望有一个包含log.txt文件image created行。让我们通过基于图像运行一个容器来检查这一点:

docker run myimage cat log.txt

当列出文件的内容时,我们将看到类似以下的输出:

Fri Sep 18 20:31:12 UTC 2020 image created

如果我们多次运行容器,我们将看到日志文件中的日期没有更改。这是有道理的,因为**run步骤是在映像生成时执行的**,而不是在容器运行时执行的。

现在,让我们再次建立我们的镜像。我们注意到日志中的创建时间没有改变。发生这种情况是因为,如果Dockerfile不变,则Docker会缓存run指令的结果。如果要使缓存无效,则需要将–no-cache选项传递给build命令。

4. cmd命令

使用**cmd指令,我们可以指定在容器启动时执行的默认命令。**让我们将一个cmd条目添加到我们的Dockerfile中,并查看其工作方式:

...

 RUN ["/log-event.sh", "image created"]

 CMD ["/log-event.sh", "container started"]

构建完映像后,现在让我们运行它并检查输出:

$ docker run myimage

 Fri Sep 18 18:27:49 UTC 2020 image created

 Fri Sep 18 18:34:06 UTC 2020 container started

如果我们多次运行,我们将看到image created的图像条目保持不变。但是container started每次运行都会启动条目更新。这显示了每次容器启动时cmd

注意,这次我们使用了稍微不同的docker run命令来启动我们的容器。让我们看看如果运行与之前相同的命令会发生什么:

$ docker run myimage cat log.txt

 Fri Sep 18 18:27:49 UTC 2020 image created

这次将忽略Dockerfile中指定cmd那是因为我们为docker run命令指定了参数。

现在让我们继续前进,看看如果Dockerfile中cmd让我们添加一个新条目,该条目将显示另一条消息:

...

 RUN ["/log-event.sh", "image created"]

 CMD ["/log-event.sh", "container started"]

 CMD ["/log-event.sh", "container running"]

构建映像并再次运行容器后,我们将找到以下输出:

$ docker run myimage

 Fri Sep 18 18:49:44 UTC 2020 image created

 Fri Sep 18 18:49:58 UTC 2020 container running

如我们所见, container started项不存在,只有container running .这是因为,如果指定了多个cmd,则仅调用最后一个cmd。

5. entrypoint命令

正如我们在上面看到的,如果在启动容器时传递任何参数,则将忽略cmd如果我们想要更大的灵活性怎么办?假设我们要自定义附加文本并将其作为参数传递给docker run命令。为此,让我们使用entrypoint.我们将指定在容器启动时运行的默认命令。而且,我们现在能够提供额外的参数。

让我们用entrypoint: cmd

...

 RUN ["/log-event.sh", "image created"]

 ENTRYPOINT ["/log-event.sh"]

现在,通过提供一个自定义文本条目来运行容器:

$ docker run myimage container running now

 Fri Sep 18 20:57:20 UTC 2020 image created

 Fri Sep 18 20:59:51 UTC 2020 container running now

我们可以看到**entrypoint行为与****cmd** .另外,它允许我们自定义在启动时执行的命令。

cmd一样,在有多个entrypoint条目的情况下,仅考虑最后一个条目。

cmdentrypoint之间的交互

我们已经使用cmdentrypoint来定义运行容器时执行的命令。现在让我们继续前进,看看如何结合使用cmdentrypoint

一种这样的用例是为entrypoint.让我们在Dockerfile中的入口点之后cmd entrypoint

...

 RUN ["/log-event.sh", "image created"]

 ENTRYPOINT ["/log-event.sh"]

 CMD ["container started"]

现在,让我们在不提供任何参数的情况下运行容器,并使用cmd指定的默认值:

$ docker run myimage

 Fri Sep 18 21:26:12 UTC 2020 image created

 Fri Sep 18 21:26:18 UTC 2020 container started

如果选择这样做,我们也可以覆盖它们:

$ docker run myimage custom event

 Fri Sep 18 21:26:12 UTC 2020 image created

 Fri Sep 18 21:27:25 UTC 2020 custom event

需要注意的是entrypoint以外壳形式使用时的不同行为。让我们更新Dockerfile中entrypoint

...

 RUN ["/log-event.sh", "image created"]

 ENTRYPOINT /log-event.sh

 CMD ["container started"]

在这种情况下,运行容器时,我们将看到Docker如何忽略传递给docker runcmd任何参数。

7.结论

在本文中,我们已经看到了Docker指令之间的差异和相似之处: runcmd,entrypoint 。我们已经观察到它们在什么时候被调用。此外,我们还研究了它们的用途以及它们如何协同工作。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *