浅析command、args、CMD、ENTRYPOINT之间关系

在 Kubernetes 中,当你在 Pod 定义中指定command和args字段时,它们对应于 Docker 容器中的ENTRYPOINT和CMD指令,但以一种特定的方式进行映射。

一、command和args

在 Kubernetes 的 Pod 定义中:

  • command字段对应于 Docker 的ENTRYPOINT。

  • args字段对应于 Docker 的CMD。

这意味着当你在 Kubernetes Pod 中指定command时,它会覆盖 Docker 镜像中定义的ENTRYPOINT。同样,当你指定args时,它会覆盖 Docker 镜像中定义的CMD。但会有一些特殊情况,比如只指定配置command的时候,只指定配置args的时候,下面会对这些情况进行详细说明

二、ENTRYPOINT和CMD

  • 容器应用进程 = ENTRYPOINT(入口点)+ CMD

  • Docker ENTRYPOINT 定义了容器启动时运行的命令。它可以是一个可执行文件或者一个脚本。

  • Docker CMD 提供了 ENTRYPOINT 的默认参数。如果没有提供 CMD,那么 ENTRYPOINT 需要是一个完整的命令。如果提供了 CMD,它可以作为 ENTRYPOINT 的参数。如果没有ENTRYPOINT,则CMD需要一个完整命令

  • 如果在 Dockerfile 中没有显式配置 ENTRYPOINT,Docker 会使用一个默认的 ENTRYPOINT。这个默认的 ENTRYPOINT 是 /bin/sh -c。

  • 针对  docker run 镜像id sleep 3600 命令:
    • 那么对于ENTRYPOINTsleep 3600参数会被追加到么Dockerfile中ENTRYPOINT指定的命令之后。也就是说,这些参数作为ENTRYPOINT指定命令的参数。
    • 对于CMD,如果docker run命令中指定了sleep 3600参数,那么Dockerfile中CMD指定的命令会被sleep 3600替换。
    • 如果docker run 镜像id --entrypoint start.sh,那么Dockerfile中的ENTRYPOINT会被覆盖

ENTRYPOINT 的两种格式

  •  ENTRYPOINT ["executable", "param1", "param2"] (exec格式,推荐)
  •  ENTRYPOINT command param1 param2 (shell 格式)

CMD指令有三种格式

  •  CMD ["executable","param1","param2"] (exec 格式,推荐)

        这种格式使用 JSON 数组来运行命令。这意味着执行的命令不会被 shell 处理,而是直接执行。这种方式通常更安全,并且是推荐的方式,因为它不会受到 shell 字符串解析规则的影响。

推荐使用 exec 格式的 CMD 指令,主要是因为这种格式直接执行命令,而不是在 shell 环境中执行。这有几个优点:

  1. 更少的层:当你使用 exec 格式时,命令不会在 shell 中启动,这意味着没有额外的 shell 进程。这使得 Docker 容器中的进程结构更简单,容器启动时创建的进程数也更少。

  2. 信号传递:使用 exec 格式,执行的命令会成为容器的 PID 1 进程。这样做的好处是,发送到容器的信号(如 SIGTERM)可以直接被应用程序捕获和处理,从而使得应用程序能够更好地响应停止请求等信号。

  3. 不会受 shell 行为的影响:在 shell 格式中,你的命令和参数会被 shell 解释。这可能导致一些不期望的行为,比如特殊字符的解析、路径展开、变量替换等。而 exec 格式不会经过 shell 解释,执行的命令和参数会被直接传递给操作系统,避免了这些问题。

  4. 安全性:因为 exec 格式的命令不会被 shell 解释,所以更不容易受到 shell 注入攻击等安全问题的影响。

  •  CMD command param1 param2 (shell 格式)

        这是最简单的格式,它在 shell 中执行命令,就像你在命令行中输入一样。当使用这种格式时,命令将在 /bin/sh -c 下执行。

  •  CMD ["param1", "param2", ...] (参数 格式)

        当使用这种格式时,需要与 ENTRYPOINT 指令一起使用。在这种情况下,CMD 提供了参数列  表,这些参数将会被发送到 ENTRYPOINT 指定的程序。

dockerinit

        dockerinit 会负责完成根目录的准备、挂载设备和目录、配置 hostname 等一系列需要在容器内进行的初始化操作。最后,它通过 execv() 系统调用,让应用进程(ENTRYPOINT + CMD)取代自己,成为容器里的 PID=1 的进程

注意

  • Dockerfile 中多个CMD 最后一个生效

  • shell和exec格式的区别,只有shell形式才会获取相关环境变量(这里环境变量指例如:$HOME)

  • docker run CMD 会覆盖 Dockerfile 中的 CMD

三、command、args、CMD、ENTRYPOINT对比

  • 替换而非追加:在 Kubernetes 中,当你设置 command 或 args 时,你是在替换 Docker 镜像中的 ENTRYPOINT 和 CMD,而不是在它们后面追加命令或参数。

  • 独立使用:你可以只设置 command(此时 args 会被忽略,command 将覆盖 Docker 容器的 ENTRYPOINT,但不会采用 Docker 容器的 CMD 作为参数),也可以只设置 args(此时会使用 Docker 镜像的 ENTRYPOINT)。

  • 灵活性:这种方式提供了灵活性,允许 Kubernetes 用户根据需要自定义容器的启动行为。

理解 command 和 args 如何影响容器的启动行为对于正确配置和调试 Kubernetes 应用至关重要。它们让你能够控制容器的运行方式,确保它们以期望的方式执行。

四者关系图
k8s poddocker最后生效的命令
commandargsentrypointcmd
配置不配置配置配置command
不配置配置配置配置entrypoint+args
配置配置配置配置command+args
不配置不配置配置配置entrypoint+cmd

四、示例

假设您有一个 Docker 镜像,其 Dockerfile 包含以下指令

ENTRYPOINT ["entrypoint.sh"]
CMD ["defaultArg"]

在这个 Docker 镜像中,entrypoint.sh是默认的ENTRYPOINT,而defaultArg是传递给它的默认CMD。

#### Kubernetes Pod 定义

如果您在 Kubernetes Pod 定义中如下设置command和args:

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  containers:
  - name: example-container
    image: example-image
    command: ["newentrypoint.sh"]
    args: ["arg1", "arg2"]

-command: ["newentrypoint.sh"]会覆盖 Docker 镜像的ENTRYPOINT为newentrypoint.sh。

-args: ["arg1", "arg2"]会覆盖 Docker 镜像的CMD为arg1和arg2。

五、总结

当您在 Kubernetes 中使用command和args时,请确保理解这些设置会如何影响容器的启动行为。如果您的容器依赖于 Dockerfile 中定义的ENTRYPOINT或CMD,更改这些值可能会导致容器以意外的方式运行或启动失败。

总结来说,Kubernetes 中的command对应于 Docker 的ENTRYPOINT,而args对应于 Docker 的CMD,并且在 Kubernetes Pod 定义中指定这些会覆盖 Docker 镜像中的相应设置。

  • 64
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值