重用继承的图像的CMD或ENTRYPOINT

Joh*_*ore 18 shell docker dockerfile

如何CMD在容器启动/重启/附加中包含我自己的shell脚本,而不删除CMD继承图像使用的?

我正在使用它,它确实执行我的脚本,但似乎覆盖PHP CMD:

FROM php

COPY start.sh /usr/local/bin

CMD ["/usr/local/bin/start.sh"]
Run Code Online (Sandbox Code Playgroud)

我该怎么办?我正避免复制/粘贴父图像的ENTRYPOINT或CMD的前景,也许这不是一个好方法.

BMi*_*tch 22

正如评论中所提到的,没有内置的解决方案.从Dockerfile,您无法看到当前CMD或的值ENTRYPOINT.run-parts如果您控制上游基础映像并在其中包含此代码,则允许下游组件进行更改,那么拥有一个解决方案是很好的.但是docker存在一个会导致问题的固有问题,容器应该只运行一个需要在前台运行的命令.因此,如果上游图像启动,它将保持运行而不会让您的后续步骤有机会运行,因此您将面临复杂性来确定运行命令的顺序,以确保单个命令最终在不退出的情况下运行.

我个人的偏好是一个更简单和硬编码的选项,添加我自己的命令或入口点,并使我的命令的最后一步到exec上游命令.您仍然需要手动识别要从上游Dockerfile调用的脚本名称.但现在在你的start.sh,你会有:

#!/bin/sh

# run various pieces of initialization code here
# ...

# kick off the upstream command:
exec /upstream-entrypoint.sh "$@"
Run Code Online (Sandbox Code Playgroud)

通过使用exec调用,您可以将pid 1传输到上游入口点,以便正确处理信号.尾随"$@"遍历任何命令行参数.如果您要在自己的脚本中处理和提取某些args set,$@则可以使用它来调整值start.sh.

  • 我仍然感到惊讶的是,当您在 Dockerfile 中扩展它时,没有一个内置选项或简单的方法来捕获父映像的 CMD。我没有接受这个答案,因为我认为肯定会有一个功能或一个好的方法来解决这个问题,但两年后我觉得我仍然误解了一些核心概念。 (4认同)
  • 截至此评论,在子 Dockerfile 中指定 ENTRYPOINT 将清除父 Dockerfile 的 CMD。您需要在 ENTRYPOINT 之后指定父级的 CMD。 (3认同)
  • 需要注意的是,如果您从定义了“ENTRYPOINT”和“CMD”的映像继承,则可能需要定义参数才能使“exec”命令正常工作。我遇到过一种情况,上游入口点至少需要一个参数,否则它将终止且没有错误且没有输出。 (2认同)
  • @JonShipman这是已知的和预期的行为:/sf/answers/3294430751/ (2认同)

Mor*_*ssi 8

如果基础映像不是您的,不幸的是您必须手动调用父命令。

如果您拥有父图像,您可以尝试这里的人的camptocamp建议。

他们基本上使用通用脚本作为调用run-parts目录的入口点。这样做是按字典顺序运行该目录中的所有脚本。因此,当您扩展图像时,您只需将新脚本放在同一个文件夹中。

但是,这意味着您必须通过为脚本添加前缀来维护顺序,这可能会失控。(想象一下父图像决定稍后添加一个新脚本......)。

无论如何,这可以工作。

更新 #1

关于在容器运行后配置的这个 docker compose 问题有一个很长的讨论。一个建议是将 docker run 或 compose 命令包装在 shell 脚本中,然后在其他命令上运行 docker exec。

如果您想使用这种方法,您基本上将父 CMD 保留为运行命令,并在 docker run 之后将您的作为 docker exec 放置。

  • 断开的链接(camptocamp) (2认同)