如何使用 Docker 获取入口点脚本?

How to source an entry point script with Docker?

我有一张 Docker 图片,我可以 运行 它:

docker run -it --entrypoint="/bin/bash" gcr.io/docker:tag

然后我可以通过以下方式获取脚本:

root@86bfac2f6ccc:/# source entrypoint.sh

脚本看起来像这样:

more entrypoint.sh
#!/bin/bash
. /env.sh
. /root/miniconda3/etc/profile.d/conda.sh
conda activate base
exec "$@"

激活基础环境:

(base) root@86bfac2f6ccc:/#

到目前为止一切顺利,但我没有设法将其包含在 Dockerfile 中或作为 docker run 的参数:

我尝试了很多东西:

例如:

docker run -it --entrypoint="/bin/bash"  gcr.io/docker:tag  source entrypoint.sh
/bin/bash: source: No such file or directory

但是脚本存在并且可以执行:

docker run -it --entrypoint="/bin/ls"  gcr.io/docker:tag -la
...
-rwxr-xr-x  1 root root   94 Apr 26 20:36 entrypoint.sh
...

或:

docker run -it --entrypoint="/bin/bash"  gcr.io/docker:tag  ". /entrypoint.sh"
/bin/bash: . /entrypoint.sh: No such file or directory

或在 Docker 文件中:

ENTRYPOINT ["source", "/entrypoint.sh"]

我想我遇到的问题可能与 source 在当前 shell.

中评估脚本有关

有什么指导可以实现我想要的吗?看起来很明显,但我不知道。

在交互式 shell 中,source 告诉 shell 从文件中读取命令而不创建子 shell。在您的情况下,您希望初始 shell 从脚本执行命令。因此,您所要做的就是将脚本作为参数提供。请尝试以下操作:

ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]

但是,它是not a good idea到运行一个shell作为容器中的初始进程。这搞砸了信号处理。您会注意到您无法使用 Ctrl-C 停止执行。 因此,使用 CMD 而不是 ENTRYPOINT 来启动 shell。 id为1的初始进程应该是最小的init进程,比如.

当Docker启动容器时,有两部分,“入口点”和“命令”。当两者都指定时,“命令”部分作为 command-line 参数传递给“入口点”部分。

特别是,您显示的脚本具有非常典型的入口点脚本模式:

#!/bin/sh
# ... do some setup ...
# then run the CMD passed as command-line arguments
exec "$@"

如果您的 Docker 文件将此脚本命名为它的 ENTRYPOINT 那么您想将您想要的命令作为“命令”部分传递给 运行。如果你 运行 你的 shell 就像

docker run --rm -it gcr.io/docker:tag sh

然后 sh 将被传递到入口点脚本,它将进行设置,然后最终 运行 它。

(请记住,source 是一个 vendor-specific 扩展,在许多 shell 中并不存在,例如 Alpine 基础图像使用的最小 BusyBox shell,但是 . 表示相同的东西并且在 POSIX 标准中。由于容器只有 运行 一个进程,因此将一个进程作为“源”也没有任何意义这个文件”;它会设置一些环境变量,然后容器退出。入口点模式进行设置,然后 运行s 主容器命令。)