gotchadockerMajor
PID 1 in containers must handle signals and reap zombie processes
Viewed 0 times
pid 1sigtermsigkilltiniinit processzombiesignal handlingdocker stop
Error Messages
Problem
The main process in a container runs as PID 1 but behaves unexpectedly: it ignores SIGTERM (so
docker stop waits 10 seconds then sends SIGKILL), or zombie processes accumulate because nothing calls wait() on them.Solution
Use an init process as PID 1. Options:
- Add
--initflag to docker run (uses tini) - Use
init: truein Compose - Install tini explicitly in Dockerfile
services:
app:
image: myapp
init: trueRUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["python", "app.py"]Why
Unix PID 1 has special behavior: the kernel does not send default signal handlers to PID 1. If your app doesn't explicitly handle SIGTERM, it's ignored. Also, orphaned child processes are adopted by PID 1 — if PID 1 doesn't call wait(), they become zombies.
Gotchas
- Shell form ENTRYPOINT makes the shell PID 1, not your app — your app won't receive SIGTERM
docker stopsends SIGTERM and waits 10 seconds (default) before SIGKILL — always handle SIGTERM- Node.js ignores SIGTERM by default unless you add a handler:
process.on('SIGTERM', () => process.exit(0)) - tini is included in official Docker base images as /usr/bin/tini or /sbin/tini on recent Alpine
Code Snippets
Compose init and graceful shutdown config
services:
app:
image: myapp
init: true # Docker injects tini as PID 1
stop_grace_period: 30s # Wait up to 30s before SIGKILLExplicit tini entrypoint in Node image
FROM node:20-alpine
# tini already available in node image as /usr/bin/tini
ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["node", "server.js"]Context
Any containerized process that spawns children or needs graceful shutdown
Revisions (0)
No revisions yet.