Docker 中的 RUN、CMD 和 Entrypoint


RUN、CMD 和 Entrypoint 命令通常让 Docker 开发者感到困惑。理解这三个命令的概念将有助于更清晰地理解它们。

当我们尝试使用 Dockerfile 构建镜像时,指令会一步一步地执行。第一个指令通常是拉取一个基础镜像,例如 Ubuntu、CentOS 等操作系统发行版。之后,我们可以通过使用 FROM 和 AS 命令包含更多镜像或修改镜像来修改基础镜像。每个这样的指令都会创建一个新的中间镜像构建,并为每个构建创建缓存。最终的 Docker 镜像可以被认为是一个分层结构,其中有一个核心或基础镜像,在其之上有几个分层的中间镜像。

为了深入理解这三个命令,我们首先需要了解 shell 形式和 exec 形式。

可执行形式 (exec form)

此形式通常用于 Entrypoint 和 CMD 命令。其形式为:

<instruction> [“executable”, “parameter”, “parameter”, ….]

当我们以这种形式执行指令时,不会进行 shell 处理,而是直接调用可执行文件。

考虑以下命令。

RUN [“apt-get”, “install”, “vim”]
ENTRYPOINT [“/bin/echo”, “TutorialsPoint”]
CMD [“/bin/echo”, “TutorialsPoint”]

如果我们用以下指令编写 Dockerfile:

ENV variable TutorialsPoint
ENTRYPOINT [“/bin/echo”, “$variable”]

当我们尝试运行镜像时,会生成以下输出。

$variable

Shell 形式

当我们使用 shell 形式执行指令时,会进行正常的 shell 处理。它在幕后调用命令 `/bin/sh -c {command}`。

其形式为:`<你的指令> <命令>`

考虑以下命令。

RUN apt-get -y update
CMD echo “TutorialsPoint”
ENTRYPOINT echo “TutorialsPoint”

以下 Dockerfile:

ENV variable TutorialsPoint
ENTRYPOINT echo “$variable”

将输出:

TutorialsPoint

现在我们已经深入了解了这两种形式,让我们继续讨论这三个命令。

RUN

RUN 命令始终在新层中执行。它允许你在现有镜像层之上安装软件包和应用程序,并在其之上创建一个新层。

它可以用 shell 形式和 exec 形式编写。示例包括:

RUN apt-get -y update (shell form)
RUN [“apt-get”, “install”, “vim”] (exec form)

CMD

使用 CMD 命令,你可以设置默认命令。如果你运行特定容器时没有指定任何命令,则会执行此命令。如果你在运行 Docker 容器时指定了命令,则会忽略默认命令。请注意,如果在 Dockerfile 中指定了多个 CMD 指令,则只会执行最后一个。

以下是执行 CMD 命令的不同方法。

  • CMD `<命令>` 参数1,参数2…… (Shell 形式)

  • CMD [`可执行命令`,“参数1”,“参数2”,……] (可执行形式)

  • CMD [`参数1`,“参数2”]

第三种方法用于设置一些额外的默认参数,当你在可执行形式中使用 ENTRYPOINT 并运行容器时没有在命令行中指定任何参数时,这些参数将插入到默认参数之后。

考虑 Dockerfile 中的以下命令。

CMD echo “TutorialsPoint”

如果你在不指定参数的情况下运行它 (docker run -it image_name),输出将是:

TutorialsPoint

如果你通过指定 CLI 参数运行它 (docker run -it image_name /bin/bash),它将简单地打开一个 bash shell。

ENTRYPOINT

它看起来类似于 CMD 命令。但是,不同之处在于,当使用 CLI 参数运行容器时,它不会忽略参数。ENTRYPOINT 命令的两种形式为:

  • ENTRYPOINT `<命令>` 参数1,参数2…… (Shell 形式)

  • ENTRYPOINT [`可执行命令`,“参数1”,“参数2”,……] (可执行形式)

当使用 ENTRYPOINT 命令的可执行形式时,它允许你使用 CMD 命令设置附加参数。如果以 shell 形式使用它,它将忽略 CMD 参数或任何 CLI 参数。

考虑以下示例。

ENTRYPOINT [“/bin/echo”, “TutorialsPoint”]
CMD [“Docker”]
  • 如果你尝试在不指定任何 CLI 参数的情况下运行容器 (docker run -it image_name),输出将是:TutorialsPoint Docker

  • 如果你指定 CLI 参数 (docker run -it image_name DockerTutorials),输出将是:TutorialsPoint DockerTutorials。

总而言之,如果你想指定默认参数并希望在指定 CLI 参数时将其覆盖,请使用 CMD 命令。如果你想运行容器并确保始终执行特定命令,请使用 ENTRYPOINT。RUN 只是用于在基础镜像之上构建附加镜像层。

更新于:2020年10月1日

5K+ 浏览量

开启你的职业生涯

完成课程获得认证

开始学习
广告