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"
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程