使用自定义入口点
创建一个自定义入口点来执行您想要的操作,然后在最后执行您的 CMD。
注意:如果您的图像已经定义了一个自定义入口点,您可能需要扩展它而不是替换它,或者您可能会更改您需要的行为。
entrypoint.sh:
#!/bin/sh
## Do whatever you need with env vars here ...
# Hand off to the CMD
exec "$@"
Dockerfile:
COPY entrypoint.sh /entrypoint.sh
RUN chmod 755 /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
Docker 将使用 CMD 作为参数运行您的入口点。如果你的 CMD 是init,那么:
/entrypoint.sh init
入口点脚本末尾的exec 负责在入口点完成所需操作时将其移交给 CMD。
为什么会这样
ENTRYPOINT 和 CMD 的使用经常让 Docker 新手感到困惑。在 cmets 中,您对此表示困惑。以下是它的工作原理和原因。
ENTRYPOINT 是在容器内运行的初始内容。它将 CMD 作为参数列表。因此,在这个例子中,容器中运行的是这个参数列表:
# ENTRYPOINT = /entrypoint.sh
# CMD = init
["/entrypoint.sh", "init"]
# or shown in a simpler form:
/entrypoint.sh init
图像不需要有入口点。如果不定义,Docker 有一个默认值:/bin/sh -c。
因此,在您原来的情况下,没有 ENTRYPOINT,并且使用 CMD init,Docker 会运行这个:
/bin/sh -c 'init'
^--------^ ^--^
| \------- CMD
\--------------- ENTRYPOINT
一开始,Docker 只提供 CMD,/bin/sh -c 被硬编码为 ENTRYPOINT(您无法更改它)。在此过程中的某个时刻,人们遇到了他们必须做更多自定义事情的用例,而 Docker 公开了 ENTRYPOINT,因此您可以将其更改为您想要的任何内容。
在我上面展示的示例中,ENTRYPOINT 被替换为自定义脚本。 (尽管它最终仍由sh 运行,因为它以#!/bin/sh 开头。)
ENTRYPOINT 将 CMD 作为参数。 entrypoint.sh 脚本的末尾是exec "$@"。由于$@ 扩展为提供给脚本的参数列表,因此变成了
exec "init"
因此,当脚本完成时,它会消失并被 init 替换为 PID 1。(这就是 exec 所做的 - 它用不同的命令替换当前进程.)
如何包含 CMD
在 cmets 中,您询问了在 Dockerfile 中添加 CMD 的问题。是的,你可以这样做。
Dockerfile:
CMD ["init"]
或者,如果您的命令还有更多内容,例如像init -a -b 这样的参数看起来像这样:
CMD ["init", "-a", "-b"]