Home > Back-end >  Dockerfile - exec form of ENTRYPOINT and shell form of CMD
Dockerfile - exec form of ENTRYPOINT and shell form of CMD

Time:12-09

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.

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.

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)?

CodePudding user response:

  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", "..."].
  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

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

This passes the shell interpreter /bin/sh as an argument to 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. 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).

I prefer a setup where CMD is always a complete shell command. 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 ["./docker-entrypoint.sh"]  # optional
CMD java $JAVA_OPTS -jar app.jar         # in a single shell-format CMD
  • Related