InterviewHubPRO
Section Overview
Q7

Question 7 of 50

Part 1: Candid Experience, Container Internals & Docker (1 - 10)

14%
DevOps & Kubernetes (50 Qs)•Part 1: Candid Experience, Container Internals & Docker (1 - 10)

Why do containers fail to handle SIGTERM/SIGINT when running as PID 1, and what is the Zombie Process Reaping problem?

The PID 1 Problem in Linux Containers

In a standard Linux system, PID 1 (typically systemd or init) has two non-delegable kernel responsibilities:

  1. Handling Signals: The Linux kernel grants PID 1 special status. If PID 1 does not explicitly install a signal handler for a signal (such as SIGTERM or SIGINT), the kernel silently ignores the signal.
  2. Reaping Zombie Processes: When a child process terminates, it enters a "Zombie" state until its parent calls wait() or waitpid(). If the parent dies first, the child is orphaned and reparented to PID 1. PID 1 must continuously call wait() to clean them up from the process table.
rust
Problem: Node/Python as PID 1
[ Host sends SIGTERM ] 
         |
         v
[ Container PID 1 (node) ] --> Has no SIGTERM handler registered!
                               Kernel ignores signal -> 30s timeout expires -> SIGKILL!
                               Result: Abrupt termination, dropped DB connections, data corruption.

Solution: Using an Init Process (tini)
[ Host sends SIGTERM ]
         |
         v
[ Container PID 1 (tini) ] --> Catches SIGTERM, cleanly forwards it to child (node)
         |                     Calls waitpid() to reap orphaned zombie processes.
         v
[ Child PID 2 (node) ]    --> Completes in-flight requests and exits gracefully (code 0).

Production Solutions

  1. Use tini as Entrypoint in Dockerfile:
dockerfile
# Alpine includes tini package
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "dist/server.js"]
  1. Docker CLI --init flag:
bash
docker run --init -d my-node-app:latest
  1. Handle signals explicitly in application runtime:
javascript
process.on('SIGTERM', async () => {
  console.log('SIGTERM received. Closing HTTP server and DB pools...');
  await server.close();
  await dbPool.end();
  process.exit(0);
});