DevOps Peach

Docker & Kubernetes · Building Docker Images with Dockerfile · Lesson 3 of 4

CMD and ENTRYPOINT

ENTRYPOINT is the main program, CMD holds the default arguments; arguments after the image name replace CMD, not ENTRYPOINT.

Practice interactively →

Two instructions, two roles

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

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.

Practice interactively →