skip to Main Content

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

2

Answers


  1. Chosen as BEST ANSWER

    It took me a while but I finally figured out what is the point of /bin/sh -c in this use-case. We can for example use tini as an entrypoint

    ENTRYPOINT ["tini", "--"]

    and then a shell for of CMD, but we need to use exec in order to replace a subshell, that is

    CMD exec java $JAVA_OPTS -jar app.jar


    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
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search