34 Matching Annotations
- Mar 2025
-
docs.docker.com docs.docker.com
-
init runs an init process (PID 1) inside the container that forwards signals and reaps processes
-
-
stackoverflow.com stackoverflow.com
-
The other role an init process can provide is to install signal handlers so signals sent from the host can be passed onto the container process. PID 1 is a bit special as it requires the process to listen for a signal for it to be received.
-
The first thing to understand is an init process doesn't magically remove zombies. A (normal) init is designed to reap zombies when the parent process that failed to wait on them exits and the zombies hang around. The init process then becomes the zombies parent and they can be cleaned up.
-
-
www.paolomainardi.com www.paolomainardi.com
-
The solution is to use docker run --init to run an init process as PID 1, that will take care of propagating the signals to the other processes, it is safe enough to be used basically always.
-
-
-
-
It protects you from software that accidentally creates zombie processes, which can (over time!) starve your entire system for PIDs (and make it unusable).
-
It ensures that the default signal handlers work for the software you run in your Docker image. For example, with Tini, SIGTERM properly terminates your process even if you didn't explicitly install a signal handler for it.
-
If you are using Docker 1.13 or greater, Tini is included in Docker itself. This includes all versions of Docker CE. To enable Tini, just pass the --init flag to docker run.
-
reaping zombies
-
performing signal forwarding
-
-
- Nov 2022
-
github.com github.com
-
The second situation would be zombie reaping. If the process spawns child processes and does not properly reap them it will lead to a full process table
-
For both of these concerns we recommend tini. It is incredibly small, has minimal external dependencies, fills each of these roles, and does only the necessary parts of reaping and signal forwarding.
-
The first being signal handling. If the process launched does not handle SIGTERM by exiting, it will not be killed since it is PID 1 in the container
-
There are two situations where an init-like process would be helpful for the container.
-
highly recommended that the resulting image be just one concern per container; predominantly this means just one process per container, so there is no need for a full init system
container images: whether to use full init process: implied here: don't need to if only using for single process (which doesn't fork, etc.)
-
-
-
Good question! This is going to be a bit long, so bear with me
-
Is whatever process you exec in your entrypoint registering signal handlers? A good way to figure this out might be to check whether your process responds properly to e.g. docker stop (or if it waits for 10 seconds before exiting)
-
Tini does install explicit signal handlers (to forward them, incidentally), so those signals no longer get dropped. Instead, they're sent to Jenkins, which is not running as PID 1 (Tini is), and therefore has default signal handlers
-
Second, if Jenkins runs as PID 1, then it may not receive the signals you send it! That's a subtlety in PID 1. Unlike other unlike processes, PID 1 does not have default signal handlers, which means that if Jenkins hasn't explicitly installed a signal handler for SIGTERM, then that signal is going to be discarded when it's sent (whereas the default behavior would have been to terminate the process).
-
Tini fixes by "forwarding signals": if you send a signal to Tini, then it sends that same signal to your child process (Jenkins in your case).
-
A second problem is that once your process has exited, Bash will proceed to exit as well. If you're not being careful, Bash might exit with exit code 0, whereas your process actually crashed (0 means "all fine"; this would cause Docker restart policies to not do what you expect). What you actually want is for Bash to return the same exit code your process had.
-
When a zombie is created (i.e. which happens when its parent exits, and therefore all chances of it ever being waited by it are gone), it is reparent to init, which is expected to reap it (which means calling wait on it).
-
In other words, someone has to clean up after "irresponsible" parents that leave their children un-wait'ed, and that's PID 1's job.
-
Now, unlike other processes, PID 1 has a unique responsibility, which is to reap zombie processes.
Tags
- init process
- init process: responsibility: reap zombie adopted orphan processes
- origin story
- init process: responsibility: forwarding exit code
- detailed explanation
- fun wording
- motivation: why did you create this?
- long, detailed explanation
- apologizing for long explanation/answer
- init process: tini
- good explanation
- subtlety
- signals: handling/tripping signals
- long explanation/answer
- special cases
- init process: responsibility: forwarding signals
Annotators
URL
-
-
github.com github.com
-
Unfortunately most init systems don't do this correctly within Docker since they're built for hardware shutdowns instead. This causes processes to be hard killed with SIGKILL, which doesn't give them a chance to correctly deinitialize things.
-
According to the Unix process model, the init process -- PID 1 -- inherits all orphaned child processes and must reap them. Most Docker containers do not have an init process that does this correctly. As a result, their containers become filled with zombie processes over time.
-
-
en.wikipedia.org en.wikipedia.org
-
When a process loses its parent, init becomes its new parent. init periodically executes the wait system call to reap any zombies with init as parent.
-
Zombie processes should not be confused with orphan processes: an orphan process is a process that is still executing, but whose parent has died. When the parent dies, the orphaned child process is adopted by init (process ID 1). When orphan processes die, they do not remain as zombie processes; instead, they are waited on by init.
-
The result is that a process that is both a zombie and an orphan will be reaped automatically.
-
-
en.wikipedia.org en.wikipedia.org
-
A low-level approach is to fork twice, running the desired process in the grandchild, and immediately terminating the child. The grandchild process is now orphaned, and is not adopted by its grandparent, but rather by init.
-
In a Unix-like operating system any orphaned process will be immediately adopted by an implementation-defined system process: the kernel sets the parent to this process
-
-
blog.phusion.nl blog.phusion.nl
-
Let's look at a concrete example. Suppose that your container contains a web server that runs a CGI script that's written in bash. The CGI script calls grep. Then the web server decides that the CGI script is taking too long and kills the script, but grep is not affected and keeps running. When grep finishes, it becomes a zombie and is adopted by the PID 1 (the web server). The web server doesn't know about grep, so it doesn't reap it, and the grep zombie stays in the system.
-
That is, instead of properly reaping adopted processes, it's probably expecting another init process to do that job, and rightly so.
-