Docker 容器的ENTRYPOINT是如何工作的?我有一个基本的 docker 图像,它有一个 ENTRYPOINT 脚本,我正在构建另一个图像,它有一个另外的 ENTRYPOINT 脚本。
当我运行图像时,两个 ENTRYPOINT 脚本都会运行吗?
如果父图像包含一行:
ENTRYPOINT ["/entrypoint-parent.sh"]
Run Code Online (Sandbox Code Playgroud)
并且您想将以下内容添加到您的子图像中:
ENTRYPOINT ["/entrypoint-child.sh"]
Run Code Online (Sandbox Code Playgroud)
然后将ENTRYPOINT结果图像中的 值替换为/entrypoint-child.sh,换句话说, 的值只有一个ENTRYPOINT。Docker 只会调用一个进程来启动您的容器,尽管该进程可以产生子进程。有几种技术可以扩展入口点。
选项 A:调用您的入口点,然后在最后运行父入口点,例如/entrypoint-child.sh可能如下所示:
#!/bin/sh
echo Running child entrypoint initialization steps here
# ...
exec /entrypoint-parent.sh "$@"
Run Code Online (Sandbox Code Playgroud)
该exec部分很重要,它用/entrypoint-parent.sh外壳或进程替换当前外壳,从而消除信号处理问题。结果是您在子入口点中运行第一个初始化,然后委托给原始的父入口点。这确实需要您跟踪父入口点的名称,可能会在基础映像的版本之间发生变化。
选项 B:在后台运行父入口点。这不太理想,因为除非您采取一些额外的步骤,否则您将不再对父进程进行错误处理。最简单的是,这在您的/entrypoint-child.sh.
#!/bin/sh
# other initialization steps
/entrypoint-parent.sh "$@" &
# potentially wait for parent to be running by polling
# run something new in the foreground, that may depend on parent processes
exec /child-process.bin
Run Code Online (Sandbox Code Playgroud)
请注意,"$@"我一直使用的符号是将 的值CMD作为参数传递给父入口点。
选项 C:切换到诸如supervisord 之类的工具。我不是这个的忠实粉丝,因为它意味着在你的容器中运行多个守护进程,你通常最好将它拆分成多个容器。当单个子进程不断失败时,您需要决定正确的响应是什么。
选项 D:与选项 A 和 B 类似,我经常创建一个入口点脚本目录,可以在映像构建的不同级别进行扩展。入口点本身没有变化,我只是将新文件添加到一个目录中,该目录根据文件名顺序调用。在我的场景中,这些脚本都在前台运行,我CMD在最后执行。您可以在我的基本映像 repo 中看到一个示例,特别是包含以下部分的entrypoint.d目录和bin/entrypointd.sh脚本:
# ...
for ep in /etc/entrypoint.d/*; do
ext="${ep##*.}"
if [ "${ext}" = "env" -a -f "${ep}" ]; then
# source files ending in ".env"
echo "Sourcing: ${ep}"
set -a && . "${ep}" && set +a
elif [ "${ext}" = "sh" -a -x "${ep}" ]; then
# run scripts ending in ".sh"
echo "Running: ${ep}"
"${ep}"
fi
done
# ...
# run command with exec to pass control
echo "Running CMD: $@"
exec "$@"
Run Code Online (Sandbox Code Playgroud)
不,只有一个入口点,因此您的脚本将替换父映像中定义的入口点。但是您的脚本可以调用(*) 或借用父图像使用的脚本中的代码。
(*) 当然,前提是这是最后一步。请注意,在设计良好的容器中,您应该将exec脚本的最后一个命令设置为容器的主进程。如果您不这样做,发送来正常终止容器的信号(SIGINT/SIGTERM)将被发送到您的脚本(不会对它们执行任何操作),而不是发送到容器“真实”进程。Thois 将 1) 使容器缓慢停止,2) 阻止正常退出:docker stop将发送 SIGTERM,如果容器没有及时(10 秒)终止,它将使用 SIGKILL。如果您的exec脚本本身就是exec命令,那么该命令将成为主进程,一切都会好起来的。
| 归档时间: |
|
| 查看次数: |
4473 次 |
| 最近记录: |