Featured image of post 浅谈容器启动命令

浅谈容器启动命令

Dockerfile 中的 ENTRYPOINT 和 CMD 与 Kubernetes 中的 command 和 args

什么是容器启动命令

在创建 POD 时,我们可以为容器指定需要执行的启动命令以及参数。如果要设置命令,就填写在配置文件的 command 字段下,如果要设置命令的参数,就填写在配置文件的 args 字段下。 一旦 Pod 创建完成,该命令及其参数就无法再进行更改了。

对于 Kubernetes 而言,配置文件中的 command 和 args 分别对应的是 Dockerfile 中的 ENTRYPOINT 和 CMD 命令。

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

在了解这几个特殊情况之前,我们先来了解下 Dockerfile 中的 ENTRYPOINT 和 CMD。

对于 Dockerfile 中的 ENTRYPOINT 和 CMD 容器应用进程 = ENTRYPOINT + CMD。

ENTRYPOINT 定义了容器启动时运行的命令。它可以是一个可执行文件或者一个脚本,例如 nginx 容器的 Dockerfile下的 ENTRYPOINT 为 /docker-entrypoint.sh。如果在 Dockerfile 中没有显式配置 ENTRYPOINT,Docker 会使用一个默认的 ENTRYPOINT。这个默认的 ENTRYPOINT 是 /bin/sh -c。

需要注意的是当一个 Dockerfile 中同时存在多条 ENTRYPOINT 时,只有最后一条ENTRYPOINT会生效。

CMD 定义了容器启动时运行的命令的参数。CMD 提供了 ENTRYPOINT 的默认参数。如果没有提供 CMD,那么 ENTRYPOINT 需要是一个完整的命令。如果提供了 CMD,它可以作为 ENTRYPOINT 的参数。反之如果没有 ENTRYPOINT,则 CMD 需要是一个完整命令。

使用的几种情况

  1. 替换而非追加:在 Kubernetes 中,当你设置 command 或 args 时,你是在替换 Docker 镜像中的 ENTRYPOINT 和 CMD,而不是在它们后面追加命令或参数。
  2. 只设置 command:当设置 command 时,Docker 镜像中的 ENTRYPOINT 将被替换,而 CMD 将被忽略。
  3. 只设置 args:当设置 args 时,Docker 镜像中的 CMD 将被替换,而 ENTRYPOINT 将被忽略。
k8s pod docker 最后生效的命令
command args entrypoint cmd
配置 配置 配置 配置 entrypoint+args
配置 不配置 配置 配置 command
不配置 配置 配置 配置 entrypoint+args
不配置 不配置 配置 配置 entrypoint+cmd
不配置 配置 不配置 配置 args
不配置 配置 配置 不配置 entrypoint+args

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

示例

有一个 例如 Bash 镜像 ,它有一个 ENTRYPOINT 和 CMD,如下所示:

1
2
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["bash"]

在这个 Dockerfile ,默认的ENTRYPOINT是docker-entrypoint.sh,而bash是传递给它的默认CMD。

只设置 command,不设置 args

Kubernetes Pod 的配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: Pod
metadata:
  name: bash
spec:
  containers:
    - name: python-container
      image: bash
      command: ["bash", "-c", "echo hello"]
      # args: ["python3 --version"]
  restartPolicy: OnFailure

可以看到输出:

1
2
# k logs bash
hello

即所执行的命令为 bash -c echo hello bash(Kubernetes yaml 中的 command+ Dockerfile 中的 CMD)。

只设置 args,不设置 command

Kubernetes Pod 的配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: Pod
metadata:
  name: bash
spec:
  containers:
    - name: python-container
      image: bash
      # command: ["bash", "-c", "echo hello"]
      args: ["python3 --version"]
  restartPolicy: OnFailure

可以看到输出:

1
2
# k logs bash
/usr/local/bin/docker-entrypoint.sh: line 11: exec: python3 --version: not found

即所执行的命令为 docker-entrypoint.sh python3 --version(Dockerfile 中的 ENTRYPOINT + Kubernetes yaml 中的 args)。

设置 command 和 args

Kubernetes Pod 的配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: v1
kind: Pod
metadata:
  name: bash
spec:
  containers:
    - name: python-container
      image: bash
      command: ["bash", "-c"]
      args: ["echo hello"]
  restartPolicy: OnFailure

可以看到输出:

1
2
# k logs bash
hello

即所执行的命令为 bash -c echo hello(Kubernetes yaml 中的 command + Kubernetes yaml 中的 args)。

不设置 command 和 args

即直接运行 Docker 镜像中的 ENTRYPOINT 和 CMD。

使用 Hugo 构建
主题 Stack 由 Jimmy 设计