Dockerfile系列:探索ENTRYPOINT与CMD的完美结合

2023年 8月 18日 60.2k 0

在使用 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,并设定了默认参数为 HelloCMD 指定了默认参数为 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 程序的 mainjava 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,它将显示总和

    • 然而,如果你尝试传递新的参数,那是行不通的。尝试 docker 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 的默认参数。它们的结合使用可以帮助我们定义灵活且可定制的容器镜像。通过实际的例子与操作指引,我们深入理解了它们的功能和使用方法。

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论