繁体   English   中英

Dockerfile - ENTRYPOINT 的执行形式和 CMD 的 shell 形式

[英]Dockerfile - exec form of ENTRYPOINT and shell form of CMD

我正在查看 Docker 的文档,以了解以 exec 形式定义的 ENTRYPOINT 和以CMD形式定义的ENTRYPOINT的行为。

文档中的示例仅显示类似exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd的内容,但没有告诉我任何信息。

例如,如果我们有:

ENV JAVA_OPTS '-XX:+UseG1GC -Xms512m -Xmx1536m'
ENTRYPOINT ["java"]
CMD $JAVA_OPTS -jar app.jar

信号传播的问题是否存在于此(换句话说,是否会在此处生成任何额外的子外壳)?

  1. 如果ENTRYPOINTCMD不是 JSON arrays,它们将被解释为字符串并转换为长度为 3 的数组["/bin/sh", "-c", "..."]
  2. 将生成的两个列表连接起来。

所以在你的例子中,最终的命令列表是

["java", "/bin/sh", "-c", "$JAVA_OPTS -jar app.jar"]

或 Bourne shell 语法

java /bin/sh -c '$JAVA_OPTS -jar app.jar'

这将 shell 解释器/bin/sh作为参数传递给java 这几乎肯定不是你想要的。

如果CMD不是完整的命令,它必须使用 JSON 数组语法,这反过来意味着它不能使用任何 shell 功能,也不能扩展环境变量引用。 这将包括“容器作为命令”模式,其中ENTRYPOINT是要运行的命令和CMD它的 arguments,以及您在此处显示的反模式,其中ENTRYPOINT仅是解释器(并且您必须重复-jar app.jar选项在docker run命令覆盖中)。

我更喜欢CMD始终是完整的 shell 命令的设置。 如果您有一个ENTRYPOINT ,它是一个脚本,它执行一些启动时设置,然后运行exec "$@"以运行作为 arguments 传递的命令。这可以接受CMD的任何一种形式。

# ENTRYPOINT ["./docker-entrypoint.sh"]  # optional
CMD java $JAVA_OPTS -jar app.jar         # in a single shell-format CMD

我花了一段时间,但我终于弄清楚/bin/sh -c在这个用例中的意义是什么。 例如,我们可以使用tini作为入口点

ENTRYPOINT ["tini", "--"]

然后是 CMD 的 shell,但是我们需要使用exec来替换子 shell,即

CMD exec java $JAVA_OPTS -jar app.jar

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM