简体   繁体   English

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

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

I am looking at Docker's documentation to understand what would be behavior of ENTRYPOINT defined in exec form and CMD defined in shell form.我正在查看 Docker 的文档,以了解以 exec 形式定义的 ENTRYPOINT 和以CMD形式定义的ENTRYPOINT的行为。

The example in the docs only shows something like exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd which does not tell me anything.文档中的示例仅显示类似exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd的内容,但没有告诉我任何信息。

For example, what if we had:例如,如果我们有:

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

Would the problem with signal propagation exist here (in other words, would any extra subshell be spawned here)?信号传播的问题是否存在于此(换句话说,是否会在此处生成任何额外的子外壳)?

  1. If either ENTRYPOINT or CMD are not JSON arrays, they are interpreted as strings and converted to a length-3 array ["/bin/sh", "-c", "..."] .如果ENTRYPOINTCMD不是 JSON arrays,它们将被解释为字符串并转换为长度为 3 的数组["/bin/sh", "-c", "..."]
  2. The resulting two lists are concatenated.将生成的两个列表连接起来。

So in your example, the final command list would be所以在你的例子中,最终的命令列表是

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

or in Bourne shell syntax或 Bourne shell 语法

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

This passes the shell interpreter /bin/sh as an argument to java ;这将 shell 解释器/bin/sh作为参数传递给java that almost certainly is not what you intend.这几乎肯定不是你想要的。

If the CMD is anything other than a complete command, it must use the JSON-array syntax, which in turn means it can't use any shell features and it can't expand environment variable references.如果CMD不是完整的命令,它必须使用 JSON 数组语法,这反过来意味着它不能使用任何 shell 功能,也不能扩展环境变量引用。 This would include both the "container-as-command" pattern where ENTRYPOINT is the command to run and CMD its arguments, and the antipattern you show here where ENTRYPOINT is the interpreter only (and you have to repeat the -jar app.jar option in a docker run command override).这将包括“容器作为命令”模式,其中ENTRYPOINT是要运行的命令和CMD它的 arguments,以及您在此处显示的反模式,其中ENTRYPOINT仅是解释器(并且您必须重复-jar app.jar选项在docker run命令覆盖中)。

I prefer a setup where CMD is always a complete shell command.我更喜欢CMD始终是完整的 shell 命令的设置。 If you have an ENTRYPOINT at all, it's a script that does some startup-time setup and then runs exec "$@" to run the command passed as arguments. This can accept either form of CMD .如果您有一个ENTRYPOINT ,它是一个脚本,它执行一些启动时设置,然后运行exec "$@"以运行作为 arguments 传递的命令。这可以接受CMD的任何一种形式。

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

It took me a while but I finally figured out what is the point of /bin/sh -c in this use-case.我花了一段时间,但我终于弄清楚/bin/sh -c在这个用例中的意义是什么。 We can for example use tini as an entrypoint例如,我们可以使用tini作为入口点

ENTRYPOINT ["tini", "--"]

and then a shell for of CMD, but we need to use exec in order to replace a subshell, that is然后是 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