我有一个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中评估脚本这一事实有关。
实现我想要的任何指导?似乎很明显,但我不明白。
答案 0 :(得分:1)
当Docker启动一个容器时,有两个部分,“入口点”和“命令”。如果同时指定了两者,则“命令”部分将作为命令行参数传递到“入口点”部分。
特别是,您显示的脚本具有一个非常典型的入口点脚本模式:
#!/bin/sh
# ... do some setup ...
# then run the CMD passed as command-line arguments
exec "$@"
如果您的Dockerfile将此脚本命名为其ENTRYPOINT
,则您希望将要运行的命令作为“命令”部分传递。如果您只运行shell
docker run --rm -it gcr.io/docker:tag sh
然后将sh
传递到入口点脚本,该脚本将进行设置,然后最终运行它。
(请记住,source
是特定于供应商的扩展,并不存在于许多shell中,例如Alpine基本映像使用的最小BusyBox shell,但是.
的含义相同,并且在POSIX标准中,由于容器仅运行一个进程,因此将一个进程“作为该文件的源”也没有任何意义;它会设置一些环境变量,然后这样做,容器退出了。入口点模式进行设置,然后运行主容器命令。)
答案 1 :(得分:0)
在交互式外壳程序中,source
告诉外壳程序从文件读取命令而不创建子外壳程序。在您的情况下,您希望初始外壳程序从脚本执行命令。因此,您要做的就是将脚本作为参数。请尝试以下操作:
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
不过,not a good idea是在容器中运行外壳程序作为初始过程。这搞砸了信号处理。您会注意到无法使用Ctrl-C停止执行。
因此,使用CMD
而不是ENTRYPOINT
启动外壳程序。 ID为1的初始进程应为最小初始化进程,例如tini
。