Why PID 1 Matters: Unraveling Linux Init and Docker Container Signals
Linux’s PID 1, the init process, is the first user‑space program that spawns all other processes, and in Docker containers it becomes the container’s root process, handling signals uniquely; understanding its behavior and using tools like Tini are essential for reliable container orchestration.
Understanding the init Process
Linux processes are arranged in a tree; each process can spawn child processes, and except for the topmost process, each has a parent.
When the system boots, the bootloader loads the kernel, which after initialization starts the first user‑space program, the init process (PID 1). The kernel looks for the init binary in standard locations such as
/sbin/init, which on most modern distributions is a symlink to
systemd. Earlier init systems include SysVinit and Upstart.
Init in Docker
In a container that has its own PID namespace, the first process also receives PID 1. This process is the container’s root process and is responsible for creating other processes inside the namespace.
Docker assigns the image’s
ENTRYPOINT(or
CMDif no entrypoint) as PID 1. This process inherits the special signal‑handling behavior of PID 1.
Special signal handling of PID 1
PID 1 differs from other processes:
It ignores any signal that has the default action, so unless the application registers a handler, it will not respond to
SIGTERM.
It never responds to the privileged signals
SIGKILLand
SIGSTOP.
For other signals, a custom handler can be registered and will be invoked.
Using Bash as PID 1
Many base images use
/bin/bashas the default command. Bash does not handle
SIGTERMby default, causing Docker’s
docker stopto wait the default 10‑second timeout before forcibly killing the container, which can lead to unclean shutdowns and zombie processes.
Moreover, if Bash exits with status 0 after a child process crashes, Docker or Kubernetes may incorrectly assume a successful termination.
A common workaround is to add an
EXITtrap that forwards signals to child processes, but this alone does not wait for children to finish, so the container may still exit prematurely.
tini as a lightweight init
For containers that need proper init behavior without the overhead of full init systems,
tiniis recommended. It can be added to an image and set as the entrypoint:
<code>FROM openjdk8:8u201-jdk-alpine3.9
RUN apk add --no-cache tini wget \
&& mkdir -p /opt/arthas \
&& cd /opt/arthas \
&& wget https://arthas.aliyun.com/arthas-boot.jar
ENTRYPOINT ["/sbin/tini", "--"]
</code>tini can reap zombie processes and forward
SIGTERMto its children, handling tasks that are difficult to implement directly in Bash or Java.
Why zombie processes appear in Docker
Although the ideal is one process per container, real‑world containers often run auxiliary processes (log rotators, monitors, etc.) or migrate multi‑process applications from VMs, leading to multiple processes and the need for an init system to reap zombies.
Summary
The key points are:
PID 1 is the first user‑space process and creates other processes in its namespace.
PID 1 has no default signal handlers; without explicit handling,
SIGTERMis ignored and
SIGKILL/
SIGSTOPcannot be caught.
Custom handlers can be registered for other signals.
Using
tinias PID 1 ensures proper signal forwarding and zombie reaping.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.