moby: Dockerfile CMD doesn't understand ENV variables
Similar to #1136.
I want to be able to say CMD [ "$CATALINA_HOME/bin/catalina.sh", "run"]
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Reactions: 9
- Comments: 31 (2 by maintainers)
Commits related to this issue
- Add note to docs about lack of shell processing in JSON form Closes #5509 Signed-off-by: Doug Davis <dug@us.ibm.com> — committed to duglin/docker by deleted user 10 years ago
- mysqld - CMD doesnt like vars According to (https://github.com/docker/docker/issues/5509) cmd does not work with env vars unless entrypoint is calling shell. Due to dictionary usage instead of string... — committed to sreinhardt/Docker-TestingSuite by deleted user 10 years ago
- Add note to docs about lack of shell processing in JSON form Closes #5509 Signed-off-by: Doug Davis <dug@us.ibm.com> — committed to nathanleclaire/docker by deleted user 10 years ago
- Add examples for JavaScript, Ruby, Groovy, Plain Java and Java Fat Jar — committed to cescoffier/vertx-stack by cescoffier 9 years ago
- [clickhouse] fix error caused by non-expanding ENV inside JSON in Dockerfile See https://github.com/docker/docker/issues/5509. — committed to nikolaynag/docker by nikolaynag 7 years ago
- startup command workaround workaround for https://github.com/moby/moby/issues/5509 — committed to geosolutions-it/docker-gs-base by randomorder 6 years ago
- change startup command workaround for https://github.com/moby/moby/issues/5509 — committed to geosolutions-it/docker-gs-base by randomorder 6 years ago
- Env variable interpolation within the CMD does require to use the sh -c pattern: https://github.com/moby/moby/issues/5509 — committed to v1v/hey-apm by v1v 5 years ago
Confirmed that the form
CMD ["sh", "-c", "echo ${MY_HOME}"]
works as expected. I’m assuming the other form will as well.Might be nice to add a note about this to the documentation.
Try
CMD echo ${MY_HOME}
orCMD ["sh", "-c", "echo ${MY_HOME}"]
and you should have more luck.The explanation is that the shell is responsible for expanding environment variables, not Docker. When you use the JSON syntax, you’re explicitly requesting that your command bypass the shell and be execed directly.
Have you tried this way?
I’d like this issue to be reopened.
The “answer” as provided above is merely a workaround, punting the expansion of ENV variables to the shell. I can immediately think of several scenarios in which this workaround is insufficient.
EDIT: Please see issue #34772, which I just created as a correlation for ARG directives. The use cases I mention there have possible overlap with the issues with ENV.
I can confirm this. Using a Dockerfile with this
And it doesn’t work on the build of the image. However, it work when you enter through /bin/bash (docker run [image] /bin/bash) and type:
Will print:
I have also tried:
With no luck.
I’ll keep trying to work around this issue
@beporter you need to add
exec
(which is a POSIX shell feature):Write the command without use the args array: ie
CMD gunicorn --bind 0.0.0.0:$PORT wsgi:app
I think this is a good example where shell expansion doesn’t work. The container is built from scratch, so it has a single binary and no shell.
@akravetz I recall on DockerConf it was said multiple times avoid using docker-entrypoint.sh, they grow massively.
The simplest solution I found was
and docker build using
I think with and without
[]
makes some difference inCMD
execution.This issue is not closed. Please reopen and fix it!
And based on @sfitts logic, as CMD is passed to the ENTRYPOINT as an argument, the following is possible:
Dockerfile:
start.sh
+1 many of us are using the ENTRYPOINT [“docker-entrypoint.sh”] CMD [“something”, “${VARIABLE”] pattern where this fails. The last line of docker-entrypoint.sh is typically
exec $@
which will not expand variables. The current proposed work-around does not handle OS signal forwarding gracefully.In case this may be useful for anyone, I wrote a small Go script to achieve this. Wrapping with shell script works but does not forward OS signals to the process.
https://github.com/abiosoft/parent
Apparently doesn’t work for me 😦
This way shell is still used to execute process. It’s basically the same as:
Read this piece: https://docs.docker.com/engine/reference/builder/#cmd
@ryanjaeb The apps will have access to the environment variables in the environment it’s run within. The shell is also an app, which is used to call other apps. So the apps called from within the shell also has access to env vars. But most apps take input/config through arguments instead of env vars, and that’s where variable expansion is needed. Hope the explanation is clear.
@ryanjaeb Wouldn’t the env vars be available within the app, and so it would not need variable expansion during call time? Assuming it’s your own binary.
Another workaround is to move the command into the script. And in there you’ll get variable expansion.