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 ./

CMD ["--foo", "bar", "--qua", "quo"]

#!/usr/bin/env bash

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 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: Logo

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

Facebook photo

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

Connecting to %s

%d bloggers like this: