Flight Engineer Flight Engineer
Flight Engineer

Dockerfile: If ENTRYPOINT is specified, variables in CMD are not getting expanded

An interesting behavior of docker build.

  When you run a container based on the image built from this Dockerfile, you will see 'This as a DO285 class'.


FROM rhel7
ENV class "/bin/echo This as a DO285 class"
#ENTRYPOINT /bin/echo
CMD $class

But a container built from the above Dockerfile with ENTRYPOINT uncommented will return nothing.


It looks like variable expansion in CMD is not happening if ENTRYPOINT is specified.  Why ?

Labels (1)
Tags (2)
0 Kudos
3 Replies
Flight Engineer Flight Engineer
Flight Engineer

Try to right using array syntax: 

ENTRYPOINT ["/bin/echo"]
CMD ["$class"]

This is because if you don't enclose them, docker will encapsulate into a sh command:

/bin/sh -c "<ENTRYPOINT>"

which can have different results from what you expect.  

0 Kudos
Flight Engineer Flight Engineer
Flight Engineer

Ricardo, I am not expecting results. I am trying to understand what I see.

Your example returns '$class' unexpanded.

The question  remains: why variable expansion in CMD is NOT happening if ENTRYPOINT is specified, and does happen when ENTRYPOINT is null.

0 Kudos

Hey, @Sergey!

What you're seeing is partly explained by what @Ricardo said just above, but to be a bit more precise. From Dockerfile(5):

         -- CMD has three forms:
                # the command is run in a shell - /bin/sh -c
                CMD command param1 param2

You are using the above form, so your /bin/echo is actually executed in a shell like this:

/bin/sh -c "$class"

Because Bourne shell can do variable expansion, this turns to:

/bin/sh -c "/bin/echo This as a DO285 class"

When you set ENTRYPOINT to /bin/echo, this changes. Again, from Dockerfile(5):

         -- ENTRYPOINT has two forms:
                # run command in a shell - /bin/sh -c
                ENTRYPOINT command param1 param2
        Specify a plain string for the ENTRYPOINT, and it will execute in
        /bin/sh -c, like a CMD instruction
        To make this optional but default, use a CMD:
                FROM ubuntu
                CMD ["-l", "-"]
                ENTRYPOINT ["/usr/bin/wc"]

 The above literally means that you can only expect ENTRYPOINT and CMD to be merged when you use the JSON notation.

So not using the array form should actually run the startup command in a shell like this:

/bin/sh -c "${ENTRYPOINT}"

So for your use case, that would be:

/bin/sh -c "/bin/echo"

Which is what you get.

What happens in the example @Ricardo suggested is that since you passed ENTRYPOINT as JSON, it is not executed in a shell:

/bin/echo $class

Because /bin/echo can not do shell variable expansion, you see $class unexpanded.

Hope this helped.

A black cat crossing the street signifies that the animal is going somewhere.
[don't forget to kudo a helpful post or mark it as a solution!]
Join the discussion
You must log in to join this conversation.