-
Notifications
You must be signed in to change notification settings - Fork 506
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
What is advantage of Tini? #8
Comments
Good question! This is going to be a bit long, so bear with me (I know you asked for brief, sorry about that :x). First, let's talk a little bit about Docker. When you run a Docker container, Docker proceeds to isolate it from the rest of the system. That isolation happens at different levels (e.g. network, filesystem, processes). Tini isn't really concerned with the network or the filesystem, so let's focus on what matters in the context of Tini: processes. Each Docker container is a PID namespace, which means that the processes in your container are isolated from other processes on your host. A PID namespace is a tree, which starts at PID 1, which is commonly called Note: when you run a Docker container, PID 1 is whatever you set as your Now, unlike other processes, PID 1 has a unique responsibility, which is to reap zombie processes. Zombie processes are processes that:
When a zombie is created (i.e. which happens when its parent exits, and therefore all chances of it ever being In other words, someone has to clean up after "irresponsible" parents that leave their children un- That's what Tini does, and is something the JVM (which is what runs when you do Note that creating zombies is usually frowned upon in the first place (i.e. ideally you should be fixing your code so it doesn't create zombies), but for something like Jenkins, they're unavoidable: since Jenkins usually runs code that isn't written by the Jenkins maintainers (i.e. your build scripts), they can't "fix the code". This is why Jenkins uses Tini: to clean up after build scripts that create zombies. Now, Bash actually does the same thing (reaping zombies), so you're probably wondering: why not use Bash as PID 1? One problem is, if you run Bash as PID 1, then all signals you send to your Docker container (e.g. using 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. Note that you can address this by creating signal handlers in Bash to actually do the forwarding, and returning a proper exit code. On the other hand that's more work, whereas adding Tini is a few lines in your Dockerfile. Now, there would be another solution, which would be to add e.g. another thread in Jenkins to reap zombies, and run Jenkins as PID 1. This isn't ideal either, for two reasons: First, if Jenkins runs as PID 1, then it's difficult to differentiate between process that were re-parented to Jenkins (which should be reaped), and processes that were spawned by Jenkins (which shouldn't, because there's other code that's already expecting to 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 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 (note: this is not the reason why Jenkins uses Tini, they use it for signal reaping, but it was used in the RabbitMQ image for that reason). Note that there are also a few extras in Tini, which would be harder to reproduce in Bash or Java (e.g. Tini can register as a subreaper so it doesn't actually need to run as PID 1 to do its zombie-reaping job), but those are mostly useful for specialist use cases. Hope this helps! Here are some references you might be interested in to learn more about that topic:
Finally, do note that there are alternatives to Tini (like Phusion's base image). Tini differentiates with:
Cheers, |
As to whether you should be using Tini. Obviously, it's not always needed (e.g. I run https://apt-browse.org/ in a dozen Docker containers, and only one of them uses Tini), but here are a few heuristics:
Now, Tini is transparent, so if you're unsure, adding it shouldn't hurt. Cheers, |
thanks for the detailed info! one thing I need to clarify... I understood that when I |
When you run
Cheers, |
(Just closing this since it's not really an issue, but just let me know if you have follow up questions) |
no prob, thanks! maybe put the two links on the readme? https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/ |
The long explanation/answer might be a good extension to the short chapter in the main README. |
You need to put this explanation in the README file. People shouldn't have to search the issues to figure out what the tool does. |
Adds a summary of #8 and a link to that discussion.
Adds a summary of #8 and a link to that discussion.
Adds a summary of #8 and a link to that discussion.
Hi Can i start supervisord with tini ? Is there a sense to do it ? What thé difference between s6 ? |
Hi @krallin, i'm currently trying to reproduce what you said about bash. You wrote:
To verify that i wrote a small c program:
I tried the following startup commands:
For each run, with --init and without --init the signal handler is being executed correctly, when using docker stop container. Does the current bash version forward all signals by default when running a command with Thanks =) Additional Info: Running on gentoo stable, docker version 17.03.2-ce |
@fbe, When you run Compare:
(this means the zombie reaping from bash is gone, obviously, since you are no longer using bash as PID 1). |
Lesson learned, thank you =) |
Write very good, thank the author's patience, benefit a lot |
Hi @krallin. Very nice utility thanks. There is another usecase that might be worth documenting in a docker context: Docker logging system is through |
good |
* Add tini to reap zombie processes * krallin/tini#8
* Add tini to reap zombie processes * krallin/tini#8
* feat: Add tini * Add tini to reap zombie processes * krallin/tini#8 * Update changelog
See this comment krallin/tini#8 (comment) for why it is a good idea to run tini.
Adding another command to the list (
And that (
--
I can confirm that. |
I guess I've figured it out how to determine if a program needs
I'm leaving aside the issue with zombie processes here. |
Hi,
| noticed the official Jenkins image was using Tini, so I was curious what it is.
It looks like it must be useful and probably solves some issues I don't know about. Could you explain very briefly in a 'Linux for dummies' kind of way what is the advantage of Tini vs just running a shell script directly as the CMD?
I have a few containers with a
docker-entrypoint.sh
type of script that basically do anexec "$@"
at the end - should I be using Tini instead?The text was updated successfully, but these errors were encountered: