Docker ENTRYPOINT (and a note about $@)

This is something I keep forgetting, so I figure I’ll write it down so it’s here for future reference.

General rule: use the exec form of ENTRYPOINT, in other words do this:

ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
CMD ["--some", "other", "--args"]

As expected, this will run apache in the foreground, with PID 1 (unless you’re being a complete idiot and using hostPID – see the note about Kubernetes BAD PODS) and it will, by default, pass the additional command-line args in the CMD clause.

However, if you pass arguments in the docker run invocation, those will override those in the CMD list, and not those in ENTRYPOINT:

docker run --rm --name apache -it massenz/apache2:0.1 --some other --stuff

will result in:

/usr/sbin/apache2ctl -D FOREGROUND --some other --stuff

There really is no way to override what ENTRYPOINT does: if you don’t like it, you’ll just have to use the container as base (FROM) and then rewrite an ENTRYPOINT of your liking.

Which brings us to the next interesting feature of ENTRYPOINT: it does not expand the $var substitutions because, after all it’s not running a shell.

So, this will fail miserably:

FROM something
ENV foo=bar
ENV qua=quo

...

ENTRYPOINT ["./my-script", "--foo", "${foo}", "--qua", "${qua}]

and your plan to be able to override bar and quo at runtime won’t work at all:

docker run --rm -d --env foo=something --env qua=else my-container

will instead fail (probably, if your script has any sense) with an error to the effect that ${foo} and ${qua} are “invalid arguments.”

The only way to make this all work is to instead use an “entrypoint script” and use $@ there:

FROM something

ADD entrypoint.sh ./
...

ENTRYPOINT ["./entrypoint.sh"]
CMD ["--foo", "bar", "--qua", "quo"]

#!/usr/bin/env bash
# entrypoint.sh

set -e

./myscript "$@"

But notice here the subtlety of wrapping the $@ in double-quotes; this will allow the following to work:

docker run --rm -d my-container --foo something --qua "this has spaces, beware"

Missing the quotes, you will get (again, if you wrote your script with a grain of brain) something along the lines of “invalid value for ‘qua’: this” or, alternatively, “unexpected argument ‘has spaces,'” or some other weird and wonderful variant.

So, here some hard-and-fast rules: even if not passing args (right now, who know what crazy stuff your future future self will come up with…), with or without spaces, with or without default argument values, so that your life can be easier:

  1. always use the exec form for ENTRYPOINT;
  2. always use double-quotes around "$@";
  3. always use set -e at the begging of your bash scripts;
  4. consider using CMD to pass default argument values for your container;
  5. seriously consider using an entrypoint.sh script to properly handle command line arguments.

There you have it, future self, good luck!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s