dockerfile cmd vs entrypoint区别

Dockerfile 中,CMDENTRYPOINT 都用于定义容器启动时运行的命令或程序,但它们有不同的作用和行为。理解它们的区别对于编写灵活的 Docker 容器非常重要。


1. CMD(默认命令)

  • CMD 用于为容器提供默认的命令和参数。这意味着,当容器启动时,如果没有指定其他命令,它将使用 CMD 中指定的命令和参数。
  • 注意:如果在 docker run 命令中提供了额外的命令或参数,CMD 将被覆盖。

语法

  • **CMD [“executable”, “param1”, “param2”]**:exec 格式,推荐使用这种方式,因为它不会启动一个额外的 shell 进程。
  • **CMD [“param1”, “param2”]**:如果使用 ENTRYPOINT 来定义执行的程序,那么 CMD 可以提供默认的参数。
  • **CMD [“executable param1 param2”]**:shell 格式,这种方式会启动一个 shell 来执行命令(例如 /bin/sh -c),有时可能会带来一些副作用,比如信号处理等。

示例

1
CMD ["echo", "Hello, World!"]

如果你运行:

1
docker run <image_name>

容器会执行 echo "Hello, World!"

如果你运行:

1
docker run <image_name> echo "Hello, Docker!"

容器会执行 echo "Hello, Docker!",并覆盖 CMD 中的命令。

2. ENTRYPOINT(入口命令)

  • ENTRYPOINT 用于指定容器启动时运行的主要命令。它确保容器总是执行特定的命令,即使你在 docker run 命令中传递了其他参数,也会传递给 ENTRYPOINT
  • ENTRYPOINT 可以通过两种方式定义:exec 格式(推荐)和 shell 格式。
  • ENTRYPOINTCMD 的关系
    • 如果同时使用 ENTRYPOINTCMDCMD 提供的参数会被附加到 ENTRYPOINT 中。
    • 如果没有指定 CMDENTRYPOINT 会直接使用默认参数。

语法

  • **ENTRYPOINT [“executable”, “param1”, “param2”]**:exec 格式,推荐使用。
  • **ENTRYPOINT [“executable param1 param2”]**:shell 格式,会启动一个 shell 来执行命令。

示例

1
2
ENTRYPOINT ["echo"]
CMD ["Hello, World!"]

这时,默认会执行 echo Hello, World!。如果运行:

1
docker run <image_name> "Hello, Docker!"

容器会执行 echo "Hello, Docker!",而 CMD 的默认参数会被覆盖。

3. CMDENTRYPOINT 配合使用

当你同时使用 CMDENTRYPOINT 时,ENTRYPOINT 会指定要执行的命令,而 CMD 可以指定默认的参数。如果 docker run 提供了新的参数,这些参数将会替代 CMD 中的参数

示例

1
2
ENTRYPOINT ["echo"]
CMD ["Hello, World!"]
  • 如果运行:

    1
    docker run <image_name>

    容器将执行 echo Hello, World!

  • 如果运行:

    1
    docker run <image_name> "Hello, Docker!"

    容器将执行 echo Hello, Docker!,覆盖了 CMD 中的默认参数。

4. 总结

特性 CMD ENTRYPOINT
目的 提供默认的执行命令或参数 指定容器启动时始终执行的命令
覆盖行为 如果 docker run 中提供了其他命令,CMD 会被覆盖 ENTRYPOINT 不会被覆盖,CMD 提供附加的参数
常见用途 提供默认命令或参数,当没有额外命令时执行 定义容器启动时必须执行的主命令
使用方式 CMD ["executable", "param1", "param2"]CMD ["param1", "param2"] ENTRYPOINT ["executable", "param1", "param2"]

5. 使用场景

  • **CMD**:

    • 用于设置默认命令和参数,当没有指定其他命令时执行。
    • 适用于那些可以被用户自定义命令或参数覆盖的场景。
  • **ENTRYPOINT**:

    • 用于设置容器的主命令,确保容器始终执行指定的命令。
    • 适用于那些不想让容器的主命令被覆盖的场景。
  • **CMD + ENTRYPOINT**:

    • 用于定义主命令并提供默认参数,同时允许通过 docker run 提供不同的参数来替换默认值。