如何在容器启动/重新启动/附加时包含自己的 shell 脚本 CMD,而不删除继承映像使用的 CMD
?
我正在使用它,它确实很好地执行了我的脚本,但是似乎覆盖了PHP CMD
:
FROM php
COPY start.sh /usr/local/bin
CMD ["/usr/local/bin/start.sh"]
我应该采取哪些不同的做法?我正在避免复制/粘贴父图像的入口点或CMD的前景,也许这不是一个好方法。
如评论中所述,没有内置的解决方案。从 Dockerfile 中,看不到当前 CMD
或 ENTRYPOINT
的值。如果您控制上游基础映像并在其中包含此代码,从而允许下游组件进行更改,那么拥有运行部件
解决方案会很好。但是 docker 有一个固有的问题会导致这个问题,容器应该只运行一个需要在前台运行的命令。因此,如果上游映像启动,它将保持运行,而不会给后续步骤运行的机会,因此您需要确定运行命令的顺序以确保单个命令最终运行而不退出。
我个人的偏好是一个简单得多的硬编码选项,添加我自己的命令或入口点,并使我的命令的最后一步< code>exec上游命令。您仍然需要手动确定要从上游Dockerfile文件调用的脚本名称。但是现在在您的< code>start.sh中,您将拥有:
#!/bin/sh
# run various pieces of initialization code here
# ...
# kick off the upstream command:
exec /upstream-entrypoint.sh "$@"
通过使用exec
调用,可以将pid 1传输到上游入口点,以便正确处理信号。后面的“$@”
通过任何命令行参数。如果您想在自己的<code>start.sh</code>脚本中处理和提取一些参数,您可以使用<code>set</code〕来调整<code>$@</code>的值。
如果基本映像不是您的,则很遗憾,您必须手动调用父命令。
如果您拥有父映像,您可以尝试camptoCamp
的人在此处提出的建议。
它们基本上使用通用脚本作为入口点,在目录上调用运行部分
。这样做的目的是按照字典顺序运行该目录中的所有脚本。因此,当你扩展一个图像时,你只需要把你的新脚本放在同一个文件夹中。
但是,这意味着您必须通过为脚本添加前缀来维持秩序,这可能会失控。(想象一下父图像决定稍后添加一个新脚本…)。
无论如何,这可以工作。
有一个关于容器运行后供应的docker compose问题的长讨论。一个建议是将docker run或compose命令包装在外壳脚本中,然后在其他命令上运行docker exec。
如果你想使用这种方法,你基本上将父CMD保留为运行命令,并在docker运行后将你的CMD作为docker exec。
以mysql镜像为例
做docker检查mysql/mysql-server: 5.7
并看到:
我们放入bootstrap.sh
(记得chmod a x):
#!/bin/bash
echo $HOSTNAME
echo "Start my initialization script..."
# docker inspect results used here
/entrypoint.sh mysqld
<code>Dockerfile</code>现在是:
FROM mysql/mysql-server:5.7
# put our script inside the image
ADD bootstrap.sh /etc/bootstrap.sh
# set to run our script
ENTRYPOINT ["/bin/sh","-c"]
CMD ["/etc/bootstrap.sh"]
建立并运行我们的新形象:
产出:
6f5be7c6d587
Start my initialization script...
[Entrypoint] MySQL Docker Image 5.7.28-1.1.13
[Entrypoint] No password option specified for new database.
...
...
您会看到这与原始图像的输出相同:
<code>docker-rm-mysql/mysql服务器:5.7</code>
[Entrypoint] MySQL Docker Image 5.7.28-1.1.13
[Entrypoint] No password option specified for new database.
...
...