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 todocker run, they replaceCMDcompletely.ENTRYPOINT: The fixed executable. It always runs. Arguments passed todocker runare 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 indocker run. - Override
ENTRYPOINT: use the--entrypointflag indocker run— useful for debugging, since it lets you drop into a shell instead of running the application at all.