1. 前言
Dockerfile中的CMD和ENTRYPOINT有什么区别?
docker run时默认执行什么命令,怎样覆盖默认命令?
pod定义中的args和command字段有什么作用?
本文,我们来回答一下这些问题。主要参考
Docker RUN vs CMD vs ENTRYPOINT
和
Mumshad Mannambeth的课程
。
2. 指令执行方式
RUN、CMD和ENTRYPOINT指令都可以有两种执行方式:shell方式和exec方式。
2.1. shell方式
shell方式格式:
<instruction> <command>
1 |
RUN apt-get install python3 |
当指令以shell方式执行时,它会在后台调用
/bin/sh -c <command>
,并且会进行常规的shell处理。例如,Dockerfile中的以下定义:
1 |
ENV name voidking |
docker run 会输出
Hello, voidking
,变量会被替换。
2.2. exec方式
exec方式格式:
<instruction> ["executable", "param1", "param2", ...]
1 |
RUN ["apt-get", "install", "python3"] |
当指令以exec方式执行时,它将直接调用可执行文件,并且不会进行shell处理。例如,Dockerfile中的以下定义:
1 |
ENV name voidking |
docker run 会输出
Hello, $name
,变量不会被替换。
如果需要运行bash而不是sh,需要使用exec方式。在这种情况下,将进行常规的shell处理。例如,Dockerfile中的以下定义:
1 |
ENV name voidking |
docker run 会输出
Hello, voidking
,变量会被替换。
3. CMD和ENTRYPOINT
3.1. CMD定义
访问 dockerhub ubuntu ,Supported tags and respective Dockerfile links,随便选择一个系统版本,这里选择 16.04 。点击链接,可以看到Dockerfile的定义。
1 |
FROM scratch |
可以看到,Dockerfile中定义了CMD为
/bin/bash
,也就是定义了默认命令为
/bin/bash
。
docker run ubuntu:16.04
会执行默认命令
/bin/bash
。
3.2. 执行特定命令
我们想要执行命令,那么需要在docker run时指定命令,覆盖默认命令。
执行sleep 3600
1 |
docker run ubuntu:16.04 sleep 3600 |
如果想要使这个特定命令永久生效,那么需要使用Dockerfile定义一个新的镜像。
1 |
FROM ubuntu:16.04 |
1 |
docker build -t ubuntu-sleeper . |
3.3. 特定参数
1 |
docker run ubuntu:16.04 sleep 3600 |
sleep命令没有变,变化的只有参数,sleep是否可以省略?可以的,定义一个新的镜像。
1 |
FROM ubuntu:16.04 |
1 |
# 生成新镜像 |
ENTRYPOINT里的命令是否可以被替换的呢?也是可以的,以执行 sleep2.0 1200 为例
1 |
docker run --entrypoint sleep2.0 ubuntu-sleeper 1200 |
综上,docker run会默认执行
ENTRYPOINT + CMD
。
通常情况下,我们会在Dockerfile中定义ENTRYPOINT作为固定命令,定义CMD作为默认参数。
4. k8s中的args和command
1 |
apiVersion: v1 |