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 只是用于在基础镜像之上构建附加镜像层。