1

Can anyone explain why is the environment variable passed by

docker run --rm -it -e APP_PORT=80 -p 8080:80 my_container <image-id> 

to CMD in Dockerfile is not resolved in following cases:

...
ARG APP_PORT
ENV APP_PORT=${APP_PORT}
...
CMD ['gunicorn', "-b", "0.0.0.0:${APP_PORT}", "main:app"]  # DOES NOT WORK!
CMD ['gunicorn', "-b", "0.0.0.0:$APP_PORT", "main:app"]    # DOES NOT WORK!

CMD ["sh", "-c", "echo 0.0.0.0:$APP_PORT"]                 # WORKS!

CMD gunicorn -b 0.0.0.0:$APP_PORT main:app                 # WORKS!

DOES NOT WORK! means I get the error: Container log - Error: '$APP_PORT' is not a valid port number.

m19v
  • 1,800
  • 4
  • 11
  • 26
  • 1
    In the exec form `CMD [...]` nothing runs a shell and nothing expands the `$APP_PORT` variable reference, that string gets passed literally as an argument to the program. In the shell form `CMD ...` Docker wraps the string in `sh -c` and that shell expands variable references. – David Maze Sep 15 '22 at 11:23

1 Answers1

1

There are 2 forms of the CMD statement, like you show.

One is the exec form, which is the one that doesn't work. It's usually preferred because it doesn't start a shell first to run the command, so it uses a little less resources.

The other is the shell form, which is the one that works. The reason that it works is that you need a shell to replace environment variables in a command. The shell form starts up a shell, that then executes your command.

As you've seen in your echo example, you can also make the exec form work by running the shell manually.

You can read more about the 2 forms here: https://docs.docker.com/engine/reference/builder/#cmd

In short, the examples that don't work, don't work because there's no shell to insert the value of the environment variable in the command.

Hans Kilian
  • 18,948
  • 1
  • 26
  • 35