19

I want to create a Docker Image that acts as an executable for which the user passes a token as an environment variable. The executable has sub commands that the user should pass via dockers CMD (think of git with authentication via Env). However, Docker does not append the CMD to the entrypoint. The relevant part of my Dockerfile looks like this:

ENTRYPOINT ["/bin/sh", "-c", "/usr/bin/mycmd --token=$MY_TOKEN"]
CMD ["pull", "stuff"]

So if this container is executed without any CMD overrides and secret as the MY_TOKEN variable, I would expect

mycmd --token=secret pull stuff

to be executed. If the user starts the container with an override, e.g.

docker run -it -e MY_TOKEN=secret myimage push junk

I would expect

mycmd --token=secret push junk

to be executed. As mentioned above, however, only mycmd --token=secret gets executed, the CMD is ignored - no matter if I override it during start or set it in the Dockerfile.

feob
  • 1,672
  • 1
  • 18
  • 30
  • 1
    did you try `docker run -it -e MY_TOKEN=secret myimage "push junk"`? – user2915097 Feb 17 '17 at 12:55
  • 1
    yes, that doesn't work either. That would also not explain why it doesn't work `without` overriding CMD in docker run – feob Feb 17 '17 at 13:01
  • 1
    try to change your CMD in the Dockerfile with `CMD ["sh", "-c", "pull", "stuff"]`, recreate an image and retest – user2915097 Feb 17 '17 at 13:06
  • 1
    try moving the whole entrypoint into another shell script. Perhaps CMD is being passed to /bin/sh rather than /usr/bin/mycmd. ENTRYPOINT ["/bin/sh", "/entrypoint.sh"] – Sahil Ahuja Feb 17 '17 at 13:22
  • 1
    Have you considered this: https://blog.docker.com/2017/02/docker-secrets-management/ – Matt Schuchard Feb 17 '17 at 13:56

2 Answers2

18

With /bin/sh -c "script" syntax, anything after the -c argument becomes an argument to your script. You can reach them with $0 and $@ as part of your /bin/sh script:

ENTRYPOINT ["/bin/sh", "-c", "exec /usr/bin/mycmd --token=$MY_TOKEN $0 $@"]
CMD ["pull", "stuff"]

Note that you could also change your entrypoint to be a shell script added to your image that runs exec /usr/bin/mycmd --token=$MY_TOKEN "$@" and execute that shell script with docker's exec syntax:

ENTRYPOINT ["/entrypoint.sh"]
BMitch
  • 148,146
  • 27
  • 334
  • 317
  • 2
    I've updated my commands to use "exec" before /usr/bin/mycmd to remove the extra shell script running as pid 1. – BMitch Feb 19 '17 at 20:57
  • 4
    +1 for using `/entrypoint.sh` and the exec. Just one thing to note: You should quote the `$@`, e.g.: `exec /usr/bin/mycmd --token=$MY_TOKEN "$@"`. Otherwise you may get strange behavior when spaces are encountered in the arguments. – Alexander Block Feb 23 '17 at 13:05
6

As specified in the docker documentation, you are specifying an entrypoint that calls a shell (thus not in the shell form, but the exec one). The parameters are passed to the shell (and therefore ignored); only the command in the shell matters. You will see your issue solved after switching your entrypoint call to:

ENTRYPOINT ["usr/bin/mycmd", "--token=$MY_TOKEN"]

Calling a shell in an entrypoint is something heavily discouraged, and precisely only useful when you want to avoid users of the image append custom parameters to your entrypoint.

See you in the interwebs! :)

David González Ruiz
  • 2,717
  • 1
  • 9
  • 10
  • 2
    This does not work, because in the exec form, no environment variabels are expanded: `docker: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"/usr/bin/mycmd --token=$MY_TOKEN\": stat /usr/bin/mycmd --token=$MY_TOKEN: no such file or directory".` – feob Feb 17 '17 at 16:02
  • The correct way would be: `ENTRYPOINT ["usr/bin/mycmd", "--token=$MY_TOKEN"]` – Ricardo Branco Feb 19 '17 at 20:29
  • 1
    this is the same line as in David's answer. Again, this does not expand the environment variable, since it utilizes the *exec* form. – feob Feb 19 '17 at 20:39
  • Sorry, I misread. This actually achieves the correct subcommand substitution. However, the problem with the missing environment variable expansion remains. – feob Feb 19 '17 at 20:46
  • I'm not sure if the problem is really missing env substitution. The way it is specified in the answer makes docker try to locate the string "usr/bin/mycmd --token=$MY_TOKEN" as a binary and thus complains with "no such file or directory". The comment made by Ricardo shows the correct syntax. – Alexander Block Feb 23 '17 at 12:58