Dockerfile系列:探索ENTRYPOINT与CMD的
在使用 Docker 构建容器镜像时,我们经常会使用 Dockerfile 来定义容器的配置。其中,ENTRYPOINT 和 CMD 是两个重要的指令,用于设置容器运行时的命令。本文将详细介绍 ENTRYPOINT 和 CMD 的主要区别,并探讨它们在 Dockerfile 中的结合使用。
CMD 与 ENTRYPOINT的主要区别
CMD
CMD指令用于设置容器运行时的默认参数。- 如果 Dockerfile 中有多个
CMD指令,只有最后一个会生效。 CMD可以被docker run命令行中的参数覆盖。- 在 Dockerfile 中,可以用 JSON 数组或字符串数组的形式指定
CMD,如CMD ["command", "arg1", "arg2"]或CMD command arg1 arg2。 CMD的参数会作为默认参数传递给 ENTRYPOINT。
ENTRYPOINT
ENTRYPOINT指令用于设置容器启动时的默认可执行命令。ENTRYPOINT可以是一个具体的命令或者一个可执行脚本。ENTRYPOINT的值不会被docker run命令行中的参数覆盖。- 在 Dockerfile 中,可以用 JSON 数组或字符串数组的形式指定
ENTRYPOINT,如ENTRYPOINT ["command", "arg1", "arg2"]或ENTRYPOINT command arg1 arg2。
CMD 与 ENTRYPOINT的结合使用
CMD 和 ENTRYPOINT 可以结合使用,以满足不同的需求。当它们同时存在时,CMD 中的参数会作为 ENTRYPOINT 的默认参数。
以下是一个示例的 Dockerfile:
FROM ubuntu:latest
ENTRYPOINT ["echo", "Hello"]
CMD ["World"]
上述 Dockerfile 中,ENTRYPOINT 指定了默认的可执行命令为 echo,并设定了默认参数为 Hello。CMD 指定了默认参数为 World。当容器启动时,会执行的命令为 echo Hello World。
可以通过以下步骤验证 ENTRYPOINT 和 CMD 的结合使用效果:
- 创建一个名为
Dockerfile的文件,并将上述示例内容复制到文件中。 - 执行以下命令构建镜像:
docker build -t myimage . - 运行容器并观察输出:
docker run myimage
运行以上命令后,会看到容器输出 Hello World,验证了 ENTRYPOINT 和 CMD 的结合运行。
需要注意的是,如果在运行容器时显式传递了命令行参数,则会覆盖 CMD 中指定的默认参数。例如,使用 docker run myimage "Greeting" 命令运行容器时,会执行的命令为 echo Greeting,而不再是 echo Hello World。
java
我们有一个 java 程序,它添加了两个数字,我们希望用户在执行 docker run 时传递参数。那么当我们容器化下面给出的程序时,我们如何实现这一点呢?
public static void main(String[] args) {
if (args.length == 2) {
int a = Integer.parseInt(args[0]);
int b = Integer.parseInt(args[1]);
int sum = a + b;
System.out.println("Sum of "+args[0] +" & "+ args[1]+" is : " + sum);
}
}
ENTRYPOINT
FROM openjdk:8-jre-alpine
COPY out/production/DockerExampleArgsJava/ /tmp
WORKDIR /tmp
ENTRYPOINT ["java", "AddTwoNumber"]
-
上述文件中的ENTRYPOINT用于指定容器启动时要运行的命令,在本例中,它通过发出命令来启动 AddTwoNumber 程序的 main
java AddTwoNumber方法 -
当你使用命令运行容器时
docker run raje/add2number,它会给出一条消息 – 请输入 2 个整数 -
您可以通过发出相同的命令并传递参数来传递参数,这些将被传递到入口点示例
docker run raje/add2number 10 100 -
如果您想在启动时将默认值传递给容器,可以通过在 Dockerfile 中提及它来实现,如下所示
FROM openjdk:8-jre-alpine
COPY out/production/DockerExampleArgsJava/ /tmp
WORKDIR /tmp
ENTRYPOINT ["java", "AddTwoNumber","5","15"]
CMD
-
如果您现在使用命令运行该程序
docker run raje/add2number,它将显示总和 -
然而,如果你尝试传递新的参数,那是行不通的。尝试 d
ocker run raje/add2number 10 100并且参数将不会被考虑 -
发生这种情况是因为我们在 dockerfile 中提供的 ENTRYPOINT 指令不会被忽略,而是会附加到原始指令中,因此在这种情况下,程序将被调用,如下所示
java AddTwoNumber 5 15 10 100 -
CMD 是另一个选项,它提供有关在执行 docker run 时应执行的操作的说明。
-
如果我们在 Dockerfile 中使用以下指令
FROM openjdk:8-jre-alpine
COPY out/production/DockerExampleArgsJava/ /tmp
WORKDIR /tmp
CMD ["java", "AddTwoNumber","5","15"]
-
执行后
docker run raje/add2number -
我们将看到输出:
Sum of 10 & 100 is : 110 -
使用 ENTRYPOINT,当我们传递新参数时,它会附加到命令中,但是使用 CMD 你可以覆盖命令,例如
-
如果你想传递新的参数,你可以运行:
docker run raje/add2number java AddTwoNumber 300 40 -
您可以将命令完全替换为类似的命令
docker run raje/add2number echo This is Test
-
-
如果您有一个场景,您希望默认命令是您提到的程序并希望用于覆盖参数,那么您可以使用 ENTRYPOINT 和 CMD 的组合
使用 ENTRYPOINT 和 CMD 的组合
FROM openjdk:8-alpine
COPY out/production/DockerExampleArgsJava/ /tmp
WORKDIR /tmp ENTRYPOINT ["java", "AddTwoNumber"]
CMD ["10","200"]
-
使用上面的 docker 文件,当您发出命令时,
docker run raje/add2number
它将输出Sum of 10 & 200 is : 210 -
您可以通过发出类似命令来覆盖默认参数
docker run raje/add2number 40 50,它将输出Sum of 40 & 50 is : 90
总结
在 Dockerfile 中,ENTRYPOINT 和 CMD 是两个重要的指令,用于设置容器运行时的命令。ENTRYPOINT 指定了默认的可执行命令,而 CMD 则提供了 ENTRYPOINT 的默认参数。它们的结合使用可以帮助我们定义灵活且可定制的容器镜像。通过实际的例子与操作指引,我们深入理解了它们的功能和使用方法。

查看9道真题和解析