Two instructions, two roles
ENTRYPOINTturns the container into an "executable": this program always runs.CMDis the default command or default arguments. Anything you type after the image name indocker runreplaces CMD.- To override ENTRYPOINT you need the
--entrypointflag.
FROM busybox:1.36
ENTRYPOINT ["ping", "-c", "3"]
CMD ["localhost"]
| Command | Process in the container |
|---|---|
docker run pinger:1.0 |
ping -c 3 localhost |
docker run pinger:1.0 192.0.2.10 |
ping -c 3 192.0.2.10 |
docker run -it --entrypoint sh pinger:1.0 |
sh |
flowchart LR E["ENTRYPOINT ping -c 3"] --> P["Final command"] C["CMD localhost<br/>(replaced by docker run arguments)"] --> P
Exec form and shell form
- Exec form
["executable", "param"](recommended): the process runs directly as PID 1 and receivesSIGTERMondocker stop. - Shell form
ENTRYPOINT ping -c 3: runs through/bin/sh -c. CMD anddocker runarguments are ignored, and signals go to the shell instead of the app, sodocker stopwaits for the timeout and then kills it.
The main process must stay in the foreground
A container lives as long as its main process runs. If the app puts itself in the background (daemon mode), the main process exits and the container stops at once. For example, nginx installed from apt needs:
CMD ["nginx", "-g", "daemon off;"]
How the two combine
No CMD |
CMD ["a"] |
|
|---|---|---|
No ENTRYPOINT |
Error: nothing to run (unless the base image sets one) | a |
ENTRYPOINT ["e"] |
e |
e a |
ENTRYPOINT e (shell form) |
/bin/sh -c e |
/bin/sh -c e (CMD ignored) |
A new CMD in a child image replaces the parent's. Setting ENTRYPOINT in a child image resets an inherited CMD, so define both again when you change the entrypoint.
Entrypoint scripts
Official images often use a script such as docker-entrypoint.sh that prepares configuration from environment variables and then starts the real program. The last line should be exec "$@", which replaces the shell with the program so it becomes PID 1 and receives signals.
#!/bin/sh
set -e
envsubst < /etc/app/config.tpl > /etc/app/config.yml
exec "$@"
PID 1 responsibilities
The process with PID 1 must handle signals and reap finished child processes. Many applications are not written for that, which leaves zombie processes or ignores SIGTERM. docker run --init adds a tiny init (tini) as PID 1 to forward signals and reap children. STOPSIGNAL SIGQUIT changes the signal docker stop sends, for programs that shut down gracefully on a different signal.
Health checks
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD wget -qO- http://localhost:8080/health || exit 1
docker ps then shows healthy or unhealthy, and Compose can wait for a healthy dependency.
The same ideas in other tools
In Compose, entrypoint: and command: override the two instructions. In Kubernetes, a container's command replaces ENTRYPOINT and args replaces CMD, a naming difference that often confuses newcomers.