Timetombs

泛义的工具是文明的基础,而确指的工具却是愚人的器物

66h / 118a
,更新于 2024-11-10T12:35:26Z+08:00 by   330589a

[Docker] Best Practice

版权声明 - CC BY-NC-SA 4.0

1 ENTRYPOINT

推荐使用ENTRYPOINT(不要和CMD同时使用) : 当ENTRYPOINT存在时,CMD会作为它的参数存在,增加复杂性。ENTRYPOINT指令ENTRYPOINT EXECENTRYPOINT 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=/

参考资料:

  1. https://docs.docker.com/engine/reference/builder/#cmd
  2. 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"
]

这时echoPID=1

当ENTRYPOINT是如下格式的时候:

[
  "/bin/sh",
  "-c",
  "echo PWD=$PWD"
]

这时shPID=1,但是echo是不是1并不确定,它依赖sh的具体行为。存在一下两种情况:

  1. shbash的软连接: 得益于bash的优化,echoPID也是1。
  2. shdash的软连接: echoPID不是1, 不过dash也有跟进这个优化,新版dash也是1。

参考连接:

  1. https://stackoverflow.com/questions/39434493/bash-c-vs-dash-c
  2. 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/

上一篇 : [Docker] Install
下一篇 : [Docker] File