Docker
ENTRYPOINT vs CMD
Short answer
ENTRYPOINT is the command that always runs. CMD is the default arguments, and anything you type after the image name replaces them.
In simple terms
Think of it as a sentence with a fixed verb and a changeable object. ENTRYPOINT is the verb — the thing this image does. CMD supplies the default object, and the person running the container can swap that object out without changing the verb.
That is why an image built to be a database has an ENTRYPOINT of the database binary, and why `docker run mydb --help` gives you the database's help rather than trying to run a program called `--help`.
If you only set CMD, there is no fixed verb — the whole sentence is replaceable, and `docker run myimage bash` gives you a shell instead of your application.
What actually happens
At start-up Docker concatenates them: the final command is `ENTRYPOINT + CMD`. Arguments passed to `docker run` after the image name replace CMD entirely; they do not append to it. Replacing ENTRYPOINT requires the explicit `--entrypoint` flag.
Both have two forms and the difference matters more than the ENTRYPOINT/CMD distinction does. Exec form — `["nginx", "-g", "daemon off;"]` — runs the binary directly as PID 1. Shell form — `nginx -g "daemon off;"` — wraps it in `/bin/sh -c`, so the shell becomes PID 1 and your process becomes its child.
That wrapping is what breaks signal handling. Docker sends SIGTERM to PID 1, and `sh -c` does not forward signals to children. So your application never receives the shutdown signal, sits there until the 10-second grace period expires, and gets SIGKILLed — which looks exactly like a hung application and is actually a quoting choice in a Dockerfile.
The pattern worth copying
# Exec form for both. The brackets are load-bearing. ENTRYPOINT ["node", "server.js"] CMD ["--port", "3000"] # docker run myapp -> node server.js --port 3000 # docker run myapp --port 8080 -> node server.js --port 8080 # docker run --entrypoint sh myapp -> sh (ENTRYPOINT overridden explicitly)
Written in shell form as `ENTRYPOINT node server.js`, the process becomes a child of sh, stops receiving SIGTERM, and every deploy takes ten seconds longer than it should while Docker waits to kill it.
◑ The mistake this causes
Using shell form, then wondering why the container ignores shutdown signals.
Why people do it Shell form looks tidier and matches how you would type the command in a terminal. The consequence — that `/bin/sh -c` becomes PID 1 and swallows signals — is invisible until something needs to stop cleanly.
What you see Containers take exactly 10 seconds to stop, every time. Graceful shutdown code never runs, so in-flight requests are dropped on every deploy and connections are not closed. `docker inspect` shows exit code 137, which is SIGKILL — the kernel eventually forcing what SIGTERM should have achieved politely.
How it shows up in production
This one hides for a long time because nothing fails outright. Deploys are just slower than they should be, and occasionally a user sees an error during a rollout.
It surfaces properly in Kubernetes, where the same problem means a pod ignores its termination signal for the whole `terminationGracePeriodSeconds`, then gets killed. Traffic keeps being routed to a pod that is trying to die, and the resulting errors look like a load-balancer problem rather than a Dockerfile one.
How to tell which one you are hitting
- Is your process actually PID 1?
- Run `docker exec <container> ps -o pid,comm` and look at what PID 1 is. If it is `sh` or `/bin/sh`, your application is a child and will not receive signals.
- Does the container take about 10 seconds to stop?
- That is the default grace period expiring. A container handling SIGTERM properly stops in well under a second.
How this gets asked in an interviewpreparation
Usually phrased as “What is the difference between ENTRYPOINT and CMD?”
What a strong answer contains Say that they concatenate, that `docker run` arguments replace CMD but not ENTRYPOINT, and then bring up exec versus shell form unprompted. The second point is the one that shows production experience, because it is the one that causes real incidents.
The follow-up “Why does exec form matter?” leads into PID 1, signal handling and graceful shutdown, which connects straight to how rolling deployments avoid dropping requests.
What comes next
Did this get you to an answer?
No text box on purpose — please do not paste production logs anywhere