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

Dr.*_*ade 3 bash entry-point docker conda

我有一个 Docker 镜像,我可以运行它:

docker run -it --entrypoint="/bin/bash" gcr.io/docker:tag
Run Code Online (Sandbox Code Playgroud)

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

root@86bfac2f6ccc:/# source entrypoint.sh
Run Code Online (Sandbox Code Playgroud)

该脚本如下所示:

more entrypoint.sh
#!/bin/bash
. /env.sh
. /root/miniconda3/etc/profile.d/conda.sh
conda activate base
exec "$@"
Run Code Online (Sandbox Code Playgroud)

激活基础环境:

(base) root@86bfac2f6ccc:/#
Run Code Online (Sandbox Code Playgroud)

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

我尝试了很多东西:

例如:

docker run -it --entrypoint="/bin/bash"  gcr.io/docker:tag  source entrypoint.sh
/bin/bash: source: No such file or directory
Run Code Online (Sandbox Code Playgroud)

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

docker run -it --entrypoint="/bin/ls"  gcr.io/docker:tag -la
...
-rwxr-xr-x  1 root root   94 Apr 26 20:36 entrypoint.sh
...
Run Code Online (Sandbox Code Playgroud)

或者:

docker run -it --entrypoint="/bin/bash"  gcr.io/docker:tag  ". /entrypoint.sh"
/bin/bash: . /entrypoint.sh: No such file or directory
Run Code Online (Sandbox Code Playgroud)

或者在 Docker 文件中:

ENTRYPOINT ["source", "/entrypoint.sh"]
Run Code Online (Sandbox Code Playgroud)

我想我遇到的问题可能与source在当前 shell中评估脚本有关。

任何指导来实现我想要的?这似乎很明显,但我不知道。

Rol*_*ber 8

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

ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
Run Code Online (Sandbox Code Playgroud)

但是,将 shell 作为容器中的初始进程运行并不是一个好主意。这会搞砸信号处理。您会注意到您无法使用 Ctrl-C 停止执行。因此,使用CMD而不是ENTRYPOINT启动shell。id 为 1 的初始进程应该是最小的 init 进程,例如tini

  • 我尝试了 tini,但也看到了同样的问题。它要么抱怨该票据不存在,要么什么也没有发生。我想我需要深入研究 CMD、ENTRYPOINT 和 sub SHELL。我将尝试构建一个非常简单的图像,该图像不是从基础图像派生的。我也尝试查看“docker描述”,但我需要了解我应该拥有什么。 (2认同)

Dav*_*aze 5

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

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

#!/bin/sh
# ... do some setup ...
# then run the CMD passed as command-line arguments
exec "$@"
Run Code Online (Sandbox Code Playgroud)

如果您的 Dockerfile 将此脚本命名为它,ENTRYPOINT那么您希望将要运行的命令作为“命令”部分传递。如果你运行你的shell

docker run --rm -it gcr.io/docker:tag sh
Run Code Online (Sandbox Code Playgroud)

thensh将被传递到入口点脚本,该脚本将进行设置并最终运行它。

(请记住,这source是一个特定于供应商的扩展,并且不存在于许多 shell 中,例如 Alpine 基础映像使用的最小 BusyBox shell,但这.意味着相同的事情并且在 POSIX 标准中。由于容器只运行一个进程,因此那个进程作为“源文件”也没有任何意义;它会设置一些环境变量,然后完成容器退出。入口点模式进行设置,然后运行主容器命令。 )