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 ?
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 -- 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 -- 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.
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.
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.
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 -- 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 -- 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.
Red Hat
Learning Community
A collaborative learning environment, enabling open source skill development.