Lesson 19 of 30
The first process in a container inherits a job it almost never asked for — and the way it responds (or doesn't) to a stop signal decides whether a deploy is clean or drops requests.
11 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
A container's main process runs as PID 1 without `--init` or an equivalent. What responsibility does it silently inherit that most application binaries were never written to handle?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
Every container runs its main process as PID 1 inside its own PID namespace — the container's version of "process ID 1," the role the kernel's real init plays on a normal machine. On a full OS, PID 1 has two jobs beyond running its own code: reaping zombie processes (cleaning up the exit status of any process whose parent already exited) and correctly forwarding signals to child processes. A real init system is built for that job. Most application binaries — a Node server, a Python script, a compiled Go binary — were never written with it in mind, because on a normal machine they'd run as PID 200-something, not PID 1.
This causes two separate, common problems. First, zombie processes accumulate if your app spawns child processes (a shell script calling other binaries, a process manager forking workers) and never explicitly reaps them — PID 1 is supposed to do that automatically for anything left orphaned, and most application code doesn't. Second, and more visibly: signal handling. When you run docker stop, Docker sends SIGTERM to PID 1, waits a grace period (10 seconds by default), and if the process hasn't exited by then, sends SIGKILL — which cannot be caught or ignored. If PID 1 doesn't have a handler for SIGTERM at all, nothing happens during the grace period, and the container gets hard-killed every single time it's stopped.
docker run --initFROM node:20-slim
COPY . .
CMD ["node", "server.js"]
docker run --init myapp
Without --init, node server.js runs as PID 1 directly. --init inserts a tiny real init process (Docker bundles tini) as PID 1 instead, which then execs node server.js as its child. That tiny init does the job a full-blown init system does — reaping zombies, forwarding signals correctly — while your actual application process runs as PID 2 or higher, exactly like it would on a normal machine, with no special PID-1 responsibilities to worry about.
--init (or a bundled tini) is not automatic — it's opt-in. docker run and Compose's init: true both require you to ask for it; plain docker run myapp gives your app PID 1 with zero init behavior for free.SIGTERM still has to actually finish work, not just acknowledge the signal. A graceful shutdown handler needs to stop accepting new connections, let in-flight requests complete, then exit — a handler that just logs "shutting down" and exits immediately still drops whatever was mid-request.SIGKILLed anyway — the fix is either shortening actual shutdown time or explicitly configuring a longer grace period, not hoping the default is enough.SIGTERM gracefully, requests still get dropped on every single deploy regardless of how careful the rollout mechanism is."Why did requests drop during our last deploy even though we use rolling updates?" is a real production question, and "the app never handled SIGTERM" is frequently the actual answer — naming PID 1's role and the SIGTERM-then-SIGKILL sequence precisely is what separates a candidate who's debugged this from one who's only read about orchestration in the abstract.