Free — no signup required

ENTRYPOINT vs. CMD: The Eternal Confusion

2 min read

How Containers Start

Every container needs a starting command. Docker provides two Dockerfile instructions for this, and their interaction confuses even experienced engineers.

  • CMD: The default command to run. Entirely replaceable. If you pass arguments to docker run, they replace CMD completely.
  • ENTRYPOINT: The fixed executable. It always runs. Arguments passed to docker run are appended to it, not replacing it.

Exec Form vs. Shell Form

Both instructions have two syntaxes, and the difference matters for signal handling (covered in the next section):

Shell form (a bare command string) runs the process via /bin/sh -c, which means the shell — not your process — becomes PID 1, and signals are not forwarded to your actual process. Exec form (a JSON array of executable and arguments) runs the command directly with no shell wrapper, so signals are forwarded straight to it. Always use exec form (["executable", "arg1", "arg2"]) unless you specifically need shell features like variable expansion.

The Best Practice Combination

Use ENTRYPOINT for the fixed executable and CMD for default arguments. This makes the container behave like a command-line tool:

FROM alpine
ENTRYPOINT ["/bin/ping", "-c", "3"]
CMD ["localhost"]
Command What Executes
docker run my-ping /bin/ping -c 3 localhost
docker run my-ping google.com /bin/ping -c 3 google.com
docker run --entrypoint /bin/sh my-ping /bin/sh (ENTRYPOINT overridden)

Overriding at Runtime

  • Override CMD: pass arguments after the image name in docker run.
  • Override ENTRYPOINT: use the --entrypoint flag in docker run — useful for debugging, since it lets you drop into a shell instead of running the application at all.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free