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:
- If either
ENTRYPOINT
orCMD
are not JSON arrays, they are interpreted as strings and converted to a length-3 array["/bin/sh", "-c", "..."]
. - 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