What is the difference between shell form and exec form for CMD and ENTRYPOINT?
Exec form is a JSON array and runs the program directly as PID 1. Shell form is a plain string run through /bin/sh -c, so the shell is PID 1 and signals like SIGTERM often never reach your app.
Explain it simply
Exec form talks to the chef directly. Shell form goes through a receptionist who may or may not pass your message on.
CMD ["node", "server.js"] is exec form: Docker starts node itself as PID 1, so docker stop delivers SIGTERM to node, which can shut down cleanly. CMD node server.js is shell form: Docker runs /bin/sh -c "node server.js". The shell becomes PID 1 and usually does not forward signals, so the app gets killed abruptly after the 10 second timeout.
Shell form does allow variable expansion like $HOME and chaining with &&, because a shell is involved. In exec form there is no shell, so CMD ["echo", "$HOME"] prints the literal text $HOME. If you need expansion, call the shell explicitly: ["sh", "-c", "echo $HOME"].
Example
# exec form: app is PID 1, receives SIGTERM
CMD ["node", "server.js"]
# shell form: /bin/sh is PID 1
CMD node server.jsWhat to say in the interview
"Exec form is a JSON array and runs the process directly as PID 1, so it receives signals and stops gracefully. Shell form wraps it in sh -c, which can swallow signals but allows variable expansion. I prefer exec form."
Common mistakes
- Writing exec form with single quotes, which is invalid JSON and silently falls back to shell form.