1 ENTRYPOINT
推荐使用ENTRYPOINT(不要和CMD同时使用) : 当ENTRYPOINT存在时,CMD会作为它的参数存在,增加复杂性。ENTRYPOINT指令ENTRYPOINT EXEC和ENTRYPOINT SHELL两种语法形式。但是不管是那种形式,都只是dockerfile中的语法形式,实际build后的结果都是统一的JSON数组格式。
1.1 EXEC
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT指令后面是JSON数组, 由于是JSON数组,那么则只能使用双引号"
而不是单引号'
。官方推荐使用EXEC方式,推荐理由是默认PID=1,但是默认的写法无法解析ENV。这里也推荐使用EXEC的方式,理由是保持和build后的结果是完全一致的清晰性。比如一下示例:
# 不需要解析ENV的场景
docker build -t entrypoint-inspect:exec1 -<<-'EOF'
FROM alpine
ENTRYPOINT ["echo", "PWD=$PWD"]
EOF
# 查看build后的Entrypoint
docker inspect entrypoint-inspect:exec1 --format '{{json .Config.Entrypoint}}'
# 输出
[
"echo",
"PWD=$PWD"
]
# 执行
docker run --rm entrypoint-inspect:exec1
# 输出,可见$PWD没有被解析
PWD=$PWD
# 需要解析ENV的场景
docker build -t entrypoint-inspect:exec2 -<<-'EOF'
FROM alpine
ENTRYPOINT ["/bin/sh", "-c", "echo PWD=$PWD"]
EOF
# 查看build后的Entrypoint
docker inspect entrypoint-inspect:exec2 --format '{{json .Config.Entrypoint}}'
# 输出
[
"/bin/sh",
"-c",
"echo PWD=$PWD"
]
# 执行
docker run --rm entrypoint-inspect:exec2
# 输出,可见$PWD已经被解析
PWD=/
1.2 SHELL
ENTRYPOINT command param1 param2
上述指令build后会被转换成["/bin/sh", "-c", "command param1 param2"]
, 此时可以使用ENV的。但是并不推荐,因为其存在转换逻辑,不够清晰,而且/bin/sh -c
的行为并不是固定的(参见PID)。示例:
docker build -t entrypoint-inspect:shell1 -<<-'EOF'
FROM alpine
ENTRYPOINT echo PWD=$PWD
EOF
# 查看build后的Entrypoint
docker inspect entrypoint-inspect:shell1 --format '{{json .Config.Entrypoint}}'
# 输出,可以发现完全等于:ENTRYPOINT ["/bin/sh", "-c", "echo PWD=$PWD"]
[
"/bin/sh",
"-c",
"echo PWD=$PWD"
]
# 执行
docker run --rm entrypoint-inspect:shell1
# 输出,可见$PWD已经被解析
PWD=/
参考资料:
- https://docs.docker.com/engine/reference/builder/#cmd
- https://docs.docker.com/engine/reference/builder/#entrypoint
2 PID
容器内的进程PID=1时才可以接受UNXI的信号信息,比如docker stop
或者docker kill
容器的时候。docker build
后的.[0].Config.Entrypoint
中的第一个元素是一个可执行程序,它的PID=1。比如一下示例。
当ENTRYPOINT是如下格式的时候:
[
"echo",
"PWD=$PWD"
]
这时echo
的PID=1
。
当ENTRYPOINT是如下格式的时候:
[
"/bin/sh",
"-c",
"echo PWD=$PWD"
]
这时sh
的PID=1
,但是echo
是不是1并不确定,它依赖sh
的具体行为。存在一下两种情况:
sh
是bash
的软连接: 得益于bash
的优化,echo
的PID
也是1。sh
是dash
的软连接:echo
的PID
不是1, 不过dash
也有跟进这个优化,新版dash
也是1。
参考连接:
- https://stackoverflow.com/questions/39434493/bash-c-vs-dash-c
- https://stackoverflow.com/questions/52968361/different-process-are-running-as-pid-1-when-running-cmd-entrypoint-in-shell-form
3 Reference
https://www.docker.com/blog/intro-guide-to-dockerfile-best-practices/