Question presented to candidate: "Your Dockerized Node service takes over 10 seconds to stop every time you deploy, even though your code has no slow shutdown logic. Why, and what fixes it?"
What a strong answer should cover:
- On Linux, PID 1 β the very first process in a container's process namespace β receives different kernel treatment than every other process: signals with no explicitly installed handler do not fall back to their default action. A plain
SIGTERMwith no handler is normally fatal to an ordinary process; as PID 1, it is silently ignored unless the process installs its own handler. - This means a Node process running as PID 1, with no
process.on("SIGTERM", ...)handler, does not stop whendocker stopsendsSIGTERMβ Docker waits its configured grace period (10s by default) and then escalates toSIGKILL, which cannot be caught or ignored by anything. - PID 1 is also responsible for reaping zombie processes. When a process's direct parent exits before it does, the orphan is reparented to PID 1. If PID 1 never calls
wait()/waitpid()on it, the exited-but-unreaped process stays as a zombie (stateZ) indefinitely, consuming a process-table slot. - The two standard fixes: (1) add an explicit
process.on("SIGTERM", ...)handler that performs graceful shutdown and callsprocess.exit(), and/or (2) run a minimal init process as real PID 1 βtini(or Docker's built-in--initflag, ordumb-init) β which correctly forwards signals to the actual application and reaps orphaned children, with zero application code changes. - The two problems (slow/hung shutdown, and zombie accumulation) share the same root cause β the process occupying PID 1 not doing PID-1-shaped bookkeeping β but are technically separate failure modes, and a good answer names both rather than only the more commonly cited shutdown-hang one.
- Multi-process setups (a Node app spawning helper processes, or an app run through a shell wrapper script as the container's
CMD) make this worse: the shell, not Node, ends up as PID 1, and a bareCMD ["npm", "start"]under npm can add yet another layer that swallows signals before Node ever sees them.
Clarifying questions expected:
- "Is the container's
CMDrunningnodedirectly, or throughnpm start/a shell script?" β an intermediate process is a common, separate cause of the same symptom. - "Is the slowness on stop, or is it zombie processes accumulating over the container's lifetime?" β these look related but are diagnosed differently.
Code / implementation expected: Yes β showing the SIGTERM handler and the Dockerfile/--init fix side by side is the concrete deliverable here.