Introduction
dumb-init is a simple process supervisor created by Yelp that solves two critical problems in Docker containers: signal forwarding and zombie process reaping. When your application runs as PID 1 inside a container, it does not receive signals like SIGTERM correctly and cannot clean up orphaned child processes. dumb-init acts as PID 1, forwarding signals to your application and reaping zombies automatically.
What dumb-init Does
- Runs as PID 1 inside a container and spawns your application as a child process
- Forwards signals (SIGTERM, SIGINT, SIGHUP, etc.) to the child process group
- Reaps zombie processes that accumulate when child processes are not properly waited on
- Adds under 700 KB to container image size as a static binary
- Exits with the same exit code as the child process for correct orchestrator behavior
Architecture Overview
dumb-init is written in C and compiles to a small static binary. When started, it forks and execs the command specified in its arguments. It installs signal handlers for all standard signals and forwards them to the child process group using kill with a negative PID. A SIGCHLD handler calls waitpid in a loop to reap any zombie children. The entire codebase is under 200 lines of C.
Self-Hosting & Configuration
- Download the static binary from GitHub releases; no package manager required
- Place it as the ENTRYPOINT in your Dockerfile before your CMD
- Use --single-child flag to forward signals only to the direct child, not the process group
- Remap signals with --rewrite flag (e.g., --rewrite 15:2 converts SIGTERM to SIGINT)
- No configuration files; all behavior is controlled via command-line flags
Key Features
- Tiny footprint — static binary under 700 KB with no dependencies
- Correct signal handling — ensures SIGTERM reaches your application for graceful shutdown
- Zombie reaping — prevents zombie process accumulation in long-running containers
- Signal rewriting — remap one signal to another for applications that only handle SIGINT
- Process group forwarding — sends signals to the entire child process group by default
Comparison with Similar Tools
- tini — similar minimal init with comparable features; dumb-init adds signal rewriting
- s6-overlay — full init and supervision suite; dumb-init is simpler with a single purpose
- supervisord — Python-based process manager; dumb-init is a tiny C binary for init duties only
- bash exec — exec replaces the shell but does not reap zombies; dumb-init handles both
- Docker --init — Docker's built-in init (uses tini); dumb-init offers signal rewriting and explicit control
FAQ
Q: Why can't my application just be PID 1? A: PID 1 has special signal semantics in Linux — it does not receive default signal handlers and must explicitly handle SIGTERM. It also must reap zombie children.
Q: How does dumb-init compare to Docker --init? A: Docker --init uses tini under the hood. dumb-init adds signal rewriting and process group forwarding options.
Q: Does dumb-init work with Kubernetes? A: Yes. Set it as the ENTRYPOINT in your container image. Kubernetes sends SIGTERM for graceful shutdown, and dumb-init forwards it correctly.
Q: What is the performance overhead? A: Negligible. dumb-init adds one fork/exec at startup and one signal handler invocation per signal received.