Commands and Arguments in Docker

如果你按照下面的方式运行了一个ubuntu容器,你将会发现一段时间后,容器退出了,为什么会发生这种情况?

这是因为,不像virtual machine,containers无意于托管os operation system,containers意图于运行指定的任务或进程,如托管一个web server或其应用的实例等,或简单的执行一些计算和分析任务,一旦任务完成,容器将会退出,容器仅存活在其内部应用在活动状态,若容器内的应用退出或崩溃,则容器将会退出。
那么问题是,谁定义了容器内该要运行着什么?

Dockerfile中command和entrypoint

如果你查看了Dockfile定义,如下的nginx dockefile,你将会看到一条cmd指令

最后的cmd ["nginx"],表示该应用在容器启动后,将会在容器内运行。对应nginx 镜像而言,它是nginx命令,对于mysql 镜像而言,它是mysql命令:

前面我们仅仅在容器内运行了一个ubuntu操作系统。
下面我们看下该ubuntu镜像的Dockerfile定义:

能够看到它使用bash作为默认命令,而bash并不是像web server或database server那样,是一个真正的进程,它是一个shell,监听来自终端的输入,在找不到终端时,它将会退出。

这就导致,当我们执行docker run ubuntu命令,运行一个容器时,默认docker并没有attach一个终端到容器内,因此bash 程序没有找到终端,然后就退出了。

因此如何指定一个不同的命令来启动容器?其中一个选项是,附加命令到docker run ,这样它将覆盖容器内定义的command,如docker run unbuntu sleep 5,此时在容器启动后,它将sleep 5s后退出

但是如何持久化该修改呢?即声明你想要该镜像所创建的容器启动后,总是执行sleep命令
此时你可以基于ubuntu镜像创建自己的镜像,并指定一条新的命令。有多种指定命令的方式,要么简单地以shell形式,或json数组形式;需要注意的是,如果以json数组形式指定命令,数组的第一个元素必须是能够执行的命令,请不要像下面这种形式指定命令,而是应该将命令和它的参数隔离开来

如果我们想要实现,启动后随眠10s,可以在启动容器的时候,传入参数:

但是多数时候,我们可能直接使用entrypoint,它接收命令行参数做append操作,也可以配置默认值,

当启动容器时候,没有指定任何的参数,cmd命令,会append到entrypoint命令后面,如

此时,若在启动容器时,指定了参数,则会替换掉dockerfile中的cmd命令

当然,如果你想要覆盖dockerfile中定义的entrypoint,则可以使用--entrypoint选项参数,如

映射到k8s yaml定义文件

另外我们比较关心的是,dockerfile中定义的command和entrypoint,映射到kubernetes资源定义文件中会是什么样的?
在启动容器时,命令行参数等价于在POD定义文件中这样来书写

我们可以在POD定义文件中,使用Args字段参数来覆盖dockerfile中的command指令;而使用command字段来覆盖dockerfile中的entrypoint指令

问题

问题1:现有如下的dockerfile定义文件,当使用该文件创建镜像并运行时,容器启动时的运行命令是什么?

FROM python:3.6-alpine
RUN pip install flask
COPY . /opt/
EXPOSE 8080
WORKDIR /opt
ENTRYPOINT ["python","app.pv"]
CMD ["--color","red"]

答:"python app.pv --color red",我们可以实践一下
构建镜像:

$ docker build -t python-flask:v1 - <<EOF
FROM python:3.6-alpine
RUN pip install flask
COPY . /opt/
EXPOSE 8080
WORKDIR /opt
ENTRYPOINT ["python","app.pv"]
CMD ["--color","red"]
EOF

启动容器:

$ docker run --name  python-flask python-flask:v1

$ docker inspect python-flask |grep -A 4  Arg
  "Args": [
      "app.pv",
      "--color",
      "red"
  ],

问题2:接着前一题,若使用下面的POD定义文件创建容器,则容器时的运行命令是什么?

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: webapp-green
  name: webapp-green
spec:
  containers:
  - command:
    - --color
    - green
    image: python-flask:v1
    name: webapp-green
    imagePullPolicy: Never

实验:创建容器

$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  labels:
    name: webapp-green
  name: webapp-green
spec:
  containers:
  - command:
    - --color
    - green
    image: python-flask:v1
    name: webapp-green
    imagePullPolicy: Never
EOF

查看所创建的容器,能够看到容器的启动命令为--color green,而不是Dockerfile中定义的--color red

$ docker ps -a |grep webapp-green
d492348904eb   19536c0bd835       "--color green"    11 seconds ago   Created                         k8s_webapp-green_webapp-green_default_28dfff93-163e-4ab8-9428-8febac6adb54_3

最终运行的容器的命令是"--color green",而不是"--color red",为什么?
我们知道POD yaml文件中的spec.containers.command对应的是dockerfile中的entrypoint,而spec.containers.args,则对应的是dockerfile中的cmd命令。
而现在POD yaml我们并没有指定args选项,则它不会覆盖dockerfile中的command定义。另外我们知道在dockerfile中的多个entrypoint仅会最后一个生效,所以在yaml中定义的会最终覆盖dockerfile中的定义的entrypoint。而entrypoint中定义的是“--color gren”,所以最终容器运行的命令也是它。

问题3:若使用下面的POD定义文件创建容器,则容器时的运行命令是什么?

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: webapp-pink
  name: webapp-pink
spec:
  containers:
  - command:  ["python","app.pv"]
    args: ["--color","pink"]
    image: python-flask:v1
    name: webapp-pink
    imagePullPolicy: Never

编排容器:

$ kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  labels:
    name: webapp-pink
  name: webapp-pink
spec:
  containers:
  - command:  ["python","app.pv"]
    args: ["--color","pink"]
    image: python-flask:v1
    name: webapp-pink
    imagePullPolicy: Never
EOF

查看容器:

$ docker ps -a |grep webapp-pink
d2a4d7e35d26   19536c0bd835                                          "python app.pv --col…"   7 seconds ago    Exited (2) 6 seconds ago              k8s_webapp-pink_webapp-pink_default_f13f6c73-0dbd-4f19-b6e6-76ea474632cc_3
eb5924e431f0   registry.aliyuncs.com/google_containers/pause:3.4.1   "/pause"                 48 seconds ago   Up 47 seconds                         k8s_POD_webapp-pink_default_f13f6c73-0dbd-4f19-b6e6-76ea474632cc_0
$ docker inspect d2a4d7e35d26|grep -A 4 Args
  "Args": [
      "app.pv",
      "--color",
      "pink"
  ],

能够看到启动命令为"python app.pv --color=pink"

posted @ 2022-11-08 10:44  cosmoswong  阅读(41)  评论(0编辑  收藏  举报