Git Product home page Git Product logo

tini's Introduction

Tini - A tiny but valid init for containers

Build Status

Tini is the simplest init you could think of.

All Tini does is spawn a single child (Tini is meant to be run in a container), and wait for it to exit all the while reaping zombies and performing signal forwarding.

Why Tini?

Using Tini has several benefits:

  • 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.
  • It does so completely transparently! Docker images that work without Tini will work with Tini without any changes.

If you'd like more detail on why this is useful, review this issue discussion: What is advantage of Tini?.

Using Tini

NOTE: 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.

NOTE: There are pre-built Docker images available for Tini. If you're currently using an Ubuntu or CentOS image as your base, you can use one of those as a drop-in replacement.

NOTE: There are Tini packages for Alpine Linux and NixOS. See below for installation instructions.

Add Tini to your container, and make it executable. Then, just invoke Tini and pass your program and its arguments as arguments to Tini.

In Docker, you will want to use an entrypoint so you don't have to remember to manually invoke Tini:

# Add Tini
ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "--"]

# Run your program under Tini
CMD ["/your/program", "-and", "-its", "arguments"]
# or docker run your-image /your/program ...

Note that you can skip the -- under certain conditions, but you might as well always include it to be safe. If you see an error message that looks like tini: invalid option -- 'c', then you need to add the --.

Arguments for Tini itself should be passed like -v in the following example: /tini -v -- /your/program.

NOTE: The binary linked above is a 64-bit dynamically-linked binary.

Signed binaries

The tini and tini-static binaries are signed using the key 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7.

You can verify their signatures using gpg (which you may install using your package manager):

ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini.asc /tini.asc
RUN gpg --batch --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 595E85A6B1B4779EA4DAAEC70B588DFF0527A9B7 \
 && gpg --batch --verify /tini.asc /tini
RUN chmod +x /tini

Verifying binaries via checksum

The tini and tini-static binaries have generated checksums (SHA1 and SHA256).

You can verify their checksums using sha1sum and sha256sum (which you may install using your package manager):

ENV TINI_VERSION v0.19.0
RUN wget --no-check-certificate --no-cookies --quiet https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-amd64 \
    && wget --no-check-certificate --no-cookies --quiet https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-amd64.sha256sum \
    && echo "$(cat tini-amd64.sha256sum)" | sha256sum -c

Alpine Linux Package

On Alpine Linux, you can use the following command to install Tini:

RUN apk add --no-cache tini
# Tini is now available at /sbin/tini
ENTRYPOINT ["/sbin/tini", "--"]

NixOS

Using Nix, you can use the following command to install Tini:

nix-env --install tini

Debian

On Debian (Buster or newer), you can use the following command to install Tini:

apt-get install tini

Note that this installs /usr/bin/tini (and /usr/bin/tini-static), not /tini.

Arch Linux

On Arch Linux, there is a package available on the AUR. Install using the official instructions or use an AUR helper:

pacaur -S tini

Other Platforms

ARM and 32-bit binaries are available! You can find the complete list of available binaries under the releases tab.

Options

Verbosity

The -v argument can be used for extra verbose output (you can pass it up to 3 times, e.g. -vvv).

Subreaping

By default, Tini needs to run as PID 1 so that it can reap zombies (by running as PID 1, zombies get re-parented to Tini).

If for some reason, you cannot run Tini as PID 1, you should register Tini as a process subreaper instead (only in Linux >= 3.4), by either:

  • Passing the -s argument to Tini (tini -s -- ...)
  • Setting the environment variable TINI_SUBREAPER (e.g. export TINI_SUBREAPER=).

This will ensure that zombies get re-parented to Tini despite Tini not running as PID 1.

NOTE: Tini will issue a warning if it detects that it isn't running as PID 1 and isn't registered as a subreaper. If you don't see a warning, you're fine.

Remapping exit codes

Tini will reuse the child's exit code when exiting, but occasionally, this may not be exactly what you want (e.g. if your child exits with 143 after receiving SIGTERM). Notably, this can be an issue with Java apps.

In this case, you can use the -e flag to remap an arbitrary exit code to 0. You can pass the flag multiple times if needed.

For example:

tini -e 143 -- ...

Process group killing

By default, Tini only kills its immediate child process. This can be inconvenient if sending a signal to that process does not have the desired effect. For example, if you do

docker run krallin/ubuntu-tini sh -c 'sleep 10'

and ctrl-C it, nothing happens: SIGINT is sent to the 'sh' process, but that shell won't react to it while it is waiting for the 'sleep' to finish.

With the -g option, Tini kills the child process group , so that every process in the group gets the signal. This corresponds more closely to what happens when you do ctrl-C etc. in a terminal: The signal is sent to the foreground process group.

Parent Death Signal

Tini can set its parent death signal, which is the signal Tini should receive when its parent exits. To set the parent death signal, use the -p flag with the name of the signal Tini should receive when its parent exits:

tini -p SIGTERM -- ...

NOTE: See this PR discussion to learn more about the parent death signal and use cases.

More

Existing Entrypoint

Tini can also be used with an existing entrypoint in your container!

Assuming your entrypoint was /docker-entrypoint.sh, then you would use:

ENTRYPOINT ["/tini", "--", "/docker-entrypoint.sh"]

Statically-Linked Version

Tini has very few dependencies (it only depends on libc), but if your container fails to start, you might want to consider using the statically-built version instead:

ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-static /tini

Size Considerations

Tini is a very small file (in the 10KB range), so it doesn't add much weight to your container.

The statically-linked version is bigger, but still < 1M.

Building Tini

If you'd rather not download the binary, you can build Tini by running cmake . && make.

Before building, you probably also want to run:

export CFLAGS="-DPR_SET_CHILD_SUBREAPER=36 -DPR_GET_CHILD_SUBREAPER=37"

This ensure that even if you're building on a system that has old Linux Kernel headers (< 3.4), Tini will be built with child subreaper support. This is usually what you want if you're going to use Tini with Docker (if your host Kernel supports Docker, it should also support child subreapers).

Understanding Tini

After spawning your process, Tini will wait for signals and forward those to the child process, and periodically reap zombie processes that may be created within your container.

When the "first" child process exits (/your/program in the examples above), Tini exits as well, with the exit code of the child process (so you can check your container's exit code to know whether the child exited successfully).

Debugging

If something isn't working just like you expect, consider increasing the verbosity level (up to 3):

tini -v    -- bash -c 'exit 1'
tini -vv   -- true
tini -vvv  -- pwd

Authors

Maintainer:

Contributors:

Special thanks to:

tini's People

Contributors

akimd avatar andrewhsu avatar antonmos avatar cmeury avatar crosbymichael avatar danilobuerger avatar dominik-bln avatar dpw avatar gangstead avatar geek avatar habbie avatar knilch0r avatar krallin avatar maxpeal avatar neersighted avatar pks-t avatar quaresmajose avatar rprieto avatar schoukri avatar tianon avatar ydcool avatar zimbatm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tini's Issues

Feature request - reload?

I know this is probably a pretty contentious topic. But I would find it immensely useful if there was some way to tell tini "I don't want the container to end, but I would like you to restart the main child process now."

Is there any way to do this or to safely layer something in that will?

Option to disable static build

It would be really nice if the CMake build would accept options to configure whether the non-static, static, or both should be built.

Build for tini-static fails on centos 7

When running cmake . && make I run into

cmake . && make
-- The C compiler identification is GNU 4.8.5
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/kstam/git/tini
Scanning dependencies of target tini
[ 50%] Building C object CMakeFiles/tini.dir/src/tini.c.o
Linking C executable tini
[ 50%] Built target tini
Scanning dependencies of target tini-static
[100%] Building C object CMakeFiles/tini-static.dir/src/tini.c.o
Linking C executable tini-static
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
make[2]: *** [tini-static] Error 1
make[1]: *** [CMakeFiles/tini-static.dir/all] Error 2
make: *** [all] Error 2

Any hints on how to go about fixing this?
Thx!

Add gpg signatures to releases

It would be nice to have a couple .asc files to be able to verify downloads and make security-concerned people feel better with that extra checkbox on the list 😉.

ARM version

Hi,

Actually I have been porting official Docker images for Elasticsearch, Logstash and Kibana to Raspberry with the intention of having a RPi version similar to officials ones.

Due to this reason I forked the repository with de purpouse of bulding a ARM (tested on RPi 2, ARMv7) version of Tini (https://github.com/ind3x/rpi-tini).

Would you mind to build and ARM version? I think that could be such a good idea to have option.

Kind regards!

tini doesn't like if SIGTERM in a child takes some time

I'll give you the gist of what I'm seeing first, then provide code examples. Basically, my CMD in my Dockerfile runs a bash script which at some point will launch a python web server. This server is set up to listen for SIGINT and SIGTERM and then shut down gracefully if it receives either of those. However, when I pass SIGTERM (via docker stop or docker kill -s TERM), tini passes it down properly but doesn't give it any time to clean up, it just exits the process immediately.

Ok, now for some examples, 3 files involved:

sig_handle.py

import sys
from time import sleep
import signal


def handler(signum, frame):
    if signum == 15:
        print("waiting after SIGTERM")
        sleep(3)
    elif signum == 2:
        print("waiting after SIGINT")
        sleep(3)
    print("----- IN PROGRAM Got Signal {}".format(signum))
    sys.exit()

catchable_sigs = set(signal.Signals) - {signal.SIGKILL, signal.SIGSTOP}
for sig in catchable_sigs:
    signal.signal(sig, handler)

while True:
    sleep(1)

sig_bash.sh

python sig_handle.py

Dockerfile

FROM python:3.5

ENV TINI_VERSION v0.14.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
ENTRYPOINT ["/tini", "-g", "-vv", "--"]

ADD sig_bash.sh /sig_bash.sh
ADD sig_handle.py /sig_handle.py

CMD ["/bin/bash", "/sig_bash.sh"]

If I run a container and pass it SIGINT I get what I'd expect, the handler catches it, waits 3 seconds, prints the IN PROGRAM message and then exits.

docker run -it --name c_tinitest tinitest
docker kill -s INT c_tinitest

container output:

c_tinitest
[INFO  tini (1)] Spawned child process '/bin/bash' with pid '7'
[DEBUG tini (1)] Passing signal: 'Interrupt'
waiting after SIGINT
----- IN PROGRAM Got Signal 2
[DEBUG tini (1)] Received SIGCHLD
[DEBUG tini (1)] Reaped child with pid: '7'
[INFO  tini (1)] Main child exited normally (with status '0')

However, if I run the docker kill with TERM instead, it doesn't do any waiting. Sometimes I'll see my program say "waiting after SIGTERM" but sometimes it says nothing (likely a race condition).

container output:

c_tinitest
[INFO  tini (1)] Spawned child process '/bin/bash' with pid '7'
[DEBUG tini (1)] Passing signal: 'Terminated'
waiting after SIGTERM
[DEBUG tini (1)] Received SIGCHLD
[DEBUG tini (1)] Reaped child with pid: '7'
[INFO  tini (1)] Main child exited with signal (with signal 'Terminated')

Is SIGTERM treated any differently than other signals? It seems since this is the signal sent by docker stop it should allow some time to do some cleanup.

"I have no name!" as user logging into docker container using tini

Hey there, this feels more like a question then a bug.
I'm currently using a Jenkins instance inside a docker container.
This image happens to use Tini as PID 1.
When I try open a shell into it with:

docker exec -it jenkins /bin/bash

I get this as username:

I have no name!@<container_id_hash>:/$

This is keeping me from using shell born ssh commands from Jenkins jobs that run in this container:

$ ssh
No user exists for uid 497

$ id
$ uid=497 gid=495 groups=495

I tried creating an user for that uid in /etc/passwd and also a group for that gid in /etc/group but it was a no deal!

I'm only able to run ssh manually if I login as jenkins user like this:

docker exec -it --user=jenkins jenkins /bin/bash

I could circle around that using ssh related plugins. But I'm really curious to understand why this happens only with docker images that use Tini as ENTRYPOINT.

Include license in strings

One of the nice things about tini is it is so nice to install. Merely download the executable and one is good to go.

However, there is a fair point that the license file should be included to. In order to keep things simple, would it be possible (or even reasonable) to have the license reproduced as a string in the final binary (e.g. visible via strings). This should be pretty easy to do. Just wondering if this would be ok.

Please provide smaller static linked binaries (eg. using musl)

Hi,

We are using a statically compiled version of tini which using musl is only 55Kb in size anymore. It would be really nice if you could add this to your releases.

$ musl-gcc -std=gnu99 -Werror -Wextra -Wall -pedantic-errors -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat tini.c -o tini -static
$ ls -la tini
-rwxr-xr-x 1 gebi gebi 56008 Jun  9 19:44 tini
$ ./tini 
tini (tini version 1.2.3git)
Usage: tini [OPTIONS] PROGRAM -- [ARGS] | --version

Execute a program under the supervision of a valid init process (tini)
...

0.8.2. fails to build for Alpine

Build command is:

build() {
    cd "$_builddir"
    export CFLAGS="-DPR_SET_CHILD_SUBREAPER=36 -DPR_GET_CHILD_SUBREAPER=37"
    cmake . || return 1
    make || return 1
}

Error log is:

-- The C compiler identification is GNU 4.9.2
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
fatal: Not a git repository (or any of the parent directories): .git
fatal: Not a git repository (or any of the parent directories): .git
-- Configuring done
-- Generating done
-- Build files have been written to: /build/src/tini-0.8.2
Scanning dependencies of target tiniScanning dependencies of target tini-static

[ 50%] [100%] Building C object CMakeFiles/tini.dir/src/tini.c.oBuilding C object CMakeFiles/tini-static.dir/src/tini.c.o

<command-line>:0:0: error: "_FORTIFY_SOURCE" redefined
<built-in>: note: this is the location of the previous definition
<command-line>:0:0: error: "_FORTIFY_SOURCE" redefined
<built-in>: note: this is the location of the previous definition
CMakeFiles/tini-static.dir/build.make:54: recipe for target 'CMakeFiles/tini-static.dir/src/tini.c.o' failed
make[2]: *** [CMakeFiles/tini-static.dir/src/tini.c.o] Error 1
CMakeFiles/Makefile2:95: recipe for target 'CMakeFiles/tini-static.dir/all' failed
make[1]: *** [CMakeFiles/tini-static.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
CMakeFiles/tini.dir/build.make:54: recipe for target 'CMakeFiles/tini.dir/src/tini.c.o' failed
make[2]: *** [CMakeFiles/tini.dir/src/tini.c.o] Error 1
CMakeFiles/Makefile2:60: recipe for target 'CMakeFiles/tini.dir/all' failed
make[1]: *** [CMakeFiles/tini.dir/all] Error 2
Makefile:136: recipe for target 'all' failed
make: *** [all] Error 2
>>> ERROR: tini: all failed
>>> tini: Uninstalling dependencies...

trapping SIGTERM when docker-compose kill rabbitmq

Hi Thomas,

The official Rabbitmq docker image is using tini to start rabbitmq. (congrats on the adoption!) I am trying to trap sigterm when the container is being killed.

function shutdown() {
        echo 'exiting - deregister from consul'
        curl http://$BRIDGE_IP:8500/v1/agent/service/deregister/$HOST
        exit 0
}
trap 'shutdown' SIGKILL SIGTERM SIGHUP SIGINT EXIT

tini -- ./docker-entrypoint.sh "$@"

i have my own script as entrypoint and call docker-entrypoint.sh from the official rabbitmq image.

...
if [ "$1" = 'rabbitmq-server' ]; then
...
    chown -R rabbitmq /var/lib/rabbitmq
    set -- gosu rabbitmq tini -- "$@"
fi

exec "$@"

my shutdown function is never executed when i kill the container. what am i missing here?

Thanks,
--arthur

Ability to execute a command on start and exit

I was wondering if it is in the scope of tini to allow for execution of a script on start and exit.

Eg something like

tini --boot /etc/init.d/1/boot --shutdown /etc/init.d/3/shutdown my_process

This clearly can be done from "my_process" but I think it may be convenient to add these switches.

Is this something you feel fits in tini or not?

32 bit build

Hi,

I am running containers with both 64bit and 32bit binaries for various test purposes. Would you mind building a 32bit release of tini for me to use directly in my Dockerfiles?

It is quite simple to do:

cmake . -DCMAKE_C_FLAGS=-m32
make

Thanks!

What is advantage of Tini?

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 an exec "$@" at the end - should I be using Tini instead?

Inappropriate ioctl at device at container startup

I'm seeing this message under certain startup conditions.

bash: cannot set terminal process group (-1): Inappropriate ioctl for device
bash: no job control in this shell

Here is the Dockerfile and our entrypoint script.

The issue may very well be ours, but I'd like to get a better idea of what is going on at least and how I might approach resolving this issue (if it merits being resolved). Any help would be greatly appreciated.

Timeout child

Idea: add a timeout parameter to tini. After timeout is reached, child is exited with != 0 status.

Since most of us are using tini with containers, which can often be of a worker nature, it would be nice to be able to timeout the task so that the container stops.

Current use case for me: I have a dockerized hubot running on ECS as a service which connects to slack. There is an error in the adapter implementation hubot-slack which causes hubot to become unresponsive after some time. If i can timeout hubot, the container would stop, causing ECS to restart the service, causing hubot to reconnect. Which is kind of nice :-).

tini does not support cmd /sbin/init

if we run a centos6 container with cmd /sbin/int in docker-ce 17.06.2 with --init, the container will start fail with error logs "init: missing runlevel
Try `init --help' for more information.
"
and we add runlevel like 3, it also can not start by error logs "init: Failed to connect to socket /com/ubuntu/upstart: Connection refused
"
but if we run it in a lower docker version like 1.12.6 without --init, it is ok to run the same images above.

Defunct processes still happen

Hi!

I'm probably doing something wrong, or at least something I'm not supposed to do, but I'm still seeing defunct processes when using tini.

The idea is to run a container with Apache and MySQL. Before both of these start, an NFS share needs to be mounted, containing the database files and files required by the application itself. MySQL is configured to read its database files from that share, as is the application.

Starting everything up is not a problem, daemons start, tests can be run, but shutting the container down is a problem. That's when I stumbled across tini, which seemed would solve the issues.

No such luck, I'm still seeing defunct processes:

    root       507  4.9  0.3 665036 56756 ?        Ssl  16:11   0:28 /usr/bin/docker daemon -H fd://
    root       537  0.0  0.0 232400 14768 ?        Ssl  16:11   0:00  \_ docker-containerd -l /var/run/docker/libcontainerd/docker-containerd.sock --runtime docker-runc --start-timeout 2m
    root     10726  0.0  0.0 274592  3360 ?        Sl   16:16   0:00      \_ docker-containerd-shim 88ae86ccaee1221bc6ee15afde41037bd5461caf7f9c51241ee855f671bfda0e /var/run/docker/libcontainerd/88ae86ccaee1221bc6
    root     10742  0.0  0.0      0     0 ?        Ss   16:16   0:00          \_ [tini]
    sshd     10765  0.2  0.0      0     0 ?        Zl   16:16   0:00              \_ [mysqld] <defunct>

Or like so:

root      1511  0.2  0.2 719456 39432 ?        Ssl  16:39   0:01 /usr/bin/docker daemon -H fd://
root      1516  0.0  0.0 362416 13456 ?        Ssl  16:39   0:00  \_ docker-containerd -l /var/run/docker/libcontainerd/docker-containerd.sock --runtime docker-runc --start-timeout 2m
root      1848  0.0  0.0 266652  3084 ?        Sl   16:39   0:00      \_ docker-containerd-shim d95d83caa0b4e23cd81a938630fbcd3738208a59311221683575833bc02d2f06 /var/run/docker/libcontainerd/d95d83caa0b4e23cd81a938630fbcd3738208a59311221
root      1863  0.0  0.0      0     0 ?        Ss   16:39   0:00          \_ [tini]
www-data  1896  0.0  0.0      0     0 ?        D    16:39   0:00              \_ [apache2]

I'm all out of ideas.

This is my Dockerfile:

FROM debian:jessie

STOPSIGNAL 9

# Install packages
ENV DEBIAN_FRONTEND noninteractive

# Configure Percona repository
RUN echo "deb http://repo.percona.com/apt jessie main" >> /etc/apt/sources.list.d/percona.list
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0x1C4CBDCDCD2EFD2A

# Update and install packages
RUN apt-get update && apt-get -y install curl nfs-common git apache2 libapache2-mod-php5 percona-server-server-5.6 php-apc php-pear php5-apcu php5-cli php5-common php5-curl php5-gd php5-intl php5-json php5-mcrypt php5-mysql php5-readline php5-tidy php5-xmlrpc && apt-get install -y --no-install-recommends psutils

# Install composer (please find a better way :'()
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer

# Add image configuration and scripts
ADD config/mysql.cnf /etc/mysql/conf.d/mysql.cnf

ADD scripts/entrypoint.sh /opt/entrypoint.sh
RUN chmod 755 /opt/entrypoint.sh

# Apache configuration
ADD /config/apache-vhost.conf /etc/apache2/sites-available/000-default.conf
RUN a2enmod rewrite

ADD https://github.com/krallin/tini/releases/download/v0.9.0/tini-static /tini
RUN chmod 755 /tini

# PHP environment variables
ENV PHP_UPLOAD_MAX_FILESIZE 10M
ENV PHP_POST_MAX_SIZE 10M

EXPOSE 80 443

ENTRYPOINT ["/tini", "--", "/opt/entrypoint.sh"]

And this is the entrypoint.sh script:

#!/usr/bin/env bash
set -x

# start rpcbind
rpcbind -f &

# mount data
mkdir -p /mnt/data/
mount -o nfsvers=3 10.1.2.3:/mnt/pool0/snapshot/1234 /mnt/data/

# start mysql
mysqld &

# start apache
source /etc/apache2/envvars
apache2 -D FOREGROUND &

# launch a shell
/bin/bash

add pre-processed license.h

I do not usually suggest this, but perhaps it's reasonable to include the license header file in git repo?

the xxd requirement is rather uncommon, and installing it is troublesome considering how differently distributions package that vim package addon (xxd comes from vim sources).

this avoids issues like: moby/moby#28548

other option would be to upload release tarball to issue, like you upload built binaries. then they can just use the tar.gz which includes the generated header file.

Add warning on reaped processes

A good program should always handle it's processes and wait() after forking them.

Have you thought of adding a --strict option for tini that would output a warning when sub-processes are being reaped?

At the moment it's possible to display this information in debug level which is too verbose and also doesn't distinguish between the main process and sub-processes being reaped.

Improve installation instructions

Hi there, maintainer of the Apache CouchDB Dockerfiles. Recently, while trying to update our official image Dockerfile, we got some feedback from @tianon that the approach in your README is sub-optimal. See: apache/couchdb-docker#28 (comment)

Would you consider updating your official installation recommendation so that we don't fall afoul of these guidelines in the future?

Invalid OpenPGP key for v0.9.0

Dockerfile

ENV TINI_VERSION=0.9.0
RUN curl -SL "https://github.com/krallin/tini/releases/download/$v{TINI_VERSION}/tini" -o /tini \
 && curl -SL "https://github.com/krallin/tini/releases/download/$v{TINI_VERSION}/tini.asc" -o /tini.asc \
 && export GNUPGHOME="$(mktemp -d)" \
 && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys 0527A9B7 \
 && gpg --batch --verify /tini.asc /tini \
 && rm -rf "$GNUPGHOME" /tini.asc \
 && chmod +x /tini

Output

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    21    0    21    0     0     37      0 --:--:-- --:--:-- --:--:--    37
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    21    0    21    0     0     36      0 --:--:-- --:--:-- --:--:--    36
gpg: keyring `/tmp/tmp.iBJOxJVo0f/secring.gpg' created
gpg: keyring `/tmp/tmp.iBJOxJVo0f/pubring.gpg' created
gpg: requesting key 0527A9B7 from hkp server ha.pool.sks-keyservers.net
gpg: /tmp/tmp.iBJOxJVo0f/trustdb.gpg: trustdb created
gpg: key 7001A4E5: public key "Thomas Orozco <[email protected]>" imported
gpg: no ultimately trusted keys found
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
gpg: no valid OpenPGP data found.
gpg: the signature could not be verified.
Please remember that the signature file (.sig or .asc)
should be the first file given on the command line.

Why tini will produce a lot of the same process, and turn off

Why tini will produce a lot of the same process, and turn off, whether to sleep 1 second or 500 milliseconds; as the red is the production process and exit
image

From the process ID, docker-init was created by tini 6 times, and finally only the process ID is 5 alive.
image

image

Signal handling

Hi,

I’m currently testing Tini and there is something I don’t understand regarding signals. I set a minimal Docker image to expose the problem I have. The image runs tini as entrypoint, tini’s getting /entrypoint (a shell script) as first argument. The image is built on top of alpine:3.6, the tini version implied is the one packaged in the distribution (0.14.0).

I’m trying to understand how the signals are handled, the basic need is being to be able to gracefuly stop a MariaDB container. It implies sending a SIGTERM to the mysqld process, so I’d like to send this signal if the container receives SIGABRT or SIGQUIT or whatever… In fact, only SIGKILL should stop the container without trying to cleanly close the MariaDB daemon.

This is the relevant parts of my Dockerfile:

COPY entrypoint /entrypoint

WORKDIR /
USER root
ENTRYPOINT ["/sbin/tini","-g","-vvv","--","/entrypoint"]

and this is my entrypoint script:

#!/bin/sh

trap_t1()  { echo SIGHUP  trapped; }
trap_t2()  { echo SIGINT  trapped; }
trap_t6()  { echo SIGABRT trapped; }
trap_t15() { echo SIGTERM trapped; }

trap trap_t1 1
trap trap_t2 2
trap trap_t6 6
trap trap_t15 15

tail -f /dev/null
  1. The signal seems to be passed only for SIG{INT,HUP,TERM}. When sending SIGABRT (using docker kill -s SIGABRT <container name> or the kill command from within the container) nothing happens. Why ?

  2. If I start the container with the help of docker-compose up and then issue a Ctrl+C in the terminal the container stops but I can’t see the message that my trap target function "trap_t2" is supposed to echo. This is surprising. I was expecting a SIGINT to be sent to the container, and then passed to the entrypoint script, so it would call "trap_t2"

  3. When I add a mysqld process, if I try to issue a kill -15 <pid of mysqld> in "trap_t2" it’s like the mysqld received another signal first (SIGINT or SIGQUIT) and so is already stopped and doesn’t receive this SIGTERM

Have a nice day.

Publish build process / support fedora ?

Hello,

I looked around but couldn't find the process you used to build the centos image found in the docker hub, and I am interested in using it in fedora linux. So if you have either a) a build process I can piggy back on or b) publish a fedora docker image that would be extremely helpful :)

tini spawning shell not CMD

Not sure if this is an issue or user error.

  • tini (version 0.9.0)
  • Docker 17.06.1-ce-rc1-mac20 (18682)
  • Alpine 3.6

I have two containers that I am experimenting using tini and su-exec with. The first container is a tomcat container and everything is working just fine, a text book example if you would.

The second container is a Redis container and this one for some reason only wants to run /bin/sh not what ever is in the CMD of the Dockerfile.

ENTRYPOINT ["/sbin/tini", "--"]
CMD ["start-app.sh", "redis-server", "/etc/redis.conf"]  

The contents of start-app.sh are not much

if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
    # Change the ownership
    chown -R redis:redis /data
    exec su-exec redis:redis "$@"                                                                                                                                                       
else
    exec "$@"
fi

When I build and run this my container exits immediately.

docker logs -f redis is empty

docker inspect -f "{{.Name}} {{.Config.Cmd}}" $(docker ps -a -q)

/redis [/bin/sh]
/tomcat [start-app.sh catalina]

So I see that Tomcat is working but for some odd reason the Redis container is only running a shell.. The weird thing is both containers inherit from the same base Alpine container except the Tomcat container adds Java 8.

Any thoughts?

It would be really, really nice to have an option to map certain exit code to 0

The rationale is the use of Tini together with software that is not able to exit cleanly when terminated with SIGINT, as is the case for the JVM.

When a JVM gets a SIGINT, it runs all shutdownhooks, and then exits with 128 + SIGINT (143). When running on OpenShifts for instance, this will give an error in the UI.

It could always be fixed within a bash-script or something alike, but that is not easy to get right.

Config option to set the tini_VERSION_GIT at build time

Docker now uses tini in the official release. Docker will check for a given git version string from tini and complain if it does not match with the given git revision. This means that if you build tini from a tarball generated from the exact required git revision, the current tini CMakeLists.txt will not detect the git revision correctly and docker will end up unhappy with the correct version of tini.

To fix this I propose that you can at build time set the tini_VERSION_GIT as a cmake config option.

For more details why this is needed, please see alpinelinux/aports#1123

Ability to set tini as the process group leader for child process

This may be a strange request, but we'd like to use tini to control a non-daemon aware process. However, we're using a container that starts up multiple services (for legacy reasons) and controls them via daemontools.

The daemontools supervisor would invoke tini, and then tini will invoke the actual process.

For security reasons, the actual service drops its privileges, but uses an "access-to-secret" system which looks at both the process user/group, as well as the process group leader's user/group to authorize access.

Currently, since tini always puts every controlled process into its own process group, this doesn't work for us.

Any suggestions? (happy to submit a pull request if you think it would make sense to add an option like this).

Explain docker-init and tini relationship

Hi noticed that docker ships tini since version 1.13 - congratulations!

I think it would help your users and others who happen to find this repo if you would mention this fact in the README.md file and also mention how to use tini with docker without installing it (simply add --init to the docker run call.

Pronunciation

Lots of debate in the office over this. Is it tini like tiny? Tini like teenie? Something else?

make fails if no .git

If .git directory is not present the command

execute_process (COMMAND git log -n 1 --date=local --pretty=format:"%h" WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" OUTPUT_VARIABLE tini_VERSION_GIT)

in CMakeLists.txt will fail with

fatal: Not a git repository (or any of the parent directories): .git

causing TINI_GIT to not get set. Causing this error:

/home/build/src/tini-0.6.0/src/tini.c: In function 'print_usage':
/home/build/src/tini-0.6.0/src/tini.c:84:80: error: expected expression before ')' token
  fprintf(file, "%s (version %s - %s)\n", basename(name), TINI_VERSION, TINI_GIT);
                                                                                ^
CMakeFiles/tini.dir/build.make:54: recipe for target 'CMakeFiles/tini.dir/src/tini.c.o' failed
make[2]: *** [CMakeFiles/tini.dir/src/tini.c.o] Error 1
CMakeFiles/Makefile2:60: recipe for target 'CMakeFiles/tini.dir/all' failed
make[1]: *** [CMakeFiles/tini.dir/all] Error 2
Makefile:136: recipe for target 'all' failed
make: *** [all] Error 2

Set -g through env variable

Since docker run --init is a boolean and allows for no configuration, it would be nice for tini to support its flags through env variables, as it does with TINI_SUBREAPER for instance.

In this case, the feature request is to add one for -g.

Thanks!

Please offer a download link for latest release, e.g. ttps://github.com/krallin/tini/releases/download/latest/tini

Please offer a download link for latest release, e.g. https://github.com/krallin/tini/releases/download/latest/tini . For people who don't run a huge production server, the version pinning might not give enough benefits (a tad more stability) with the huge downside of forgetting to update the pinning when running lots of custom Dockerfile images with tini in it. Therefore, being able to simply always use the latest release would be hugely appreciated.

How can i receive signal in the jvm?

I use /bin/bash to run jvm as a child process, but i can't receive signal in the jvm.

Dockerfile:

ENTRYPOINT ["/tini", "--", "/docker-entrypoint.sh"]

and docker-entrypoint.sh:

#!/bin/bash

source `dirname $0`/init-product.sh

if [ -z "$POOL_TYPE" ]; then
  source `dirname $0`/init.sh $RESOURCE_ID
  echo "****FINISHED****"
else
  echo "****FINISHED****"
  java -Xmx64m -Xms16m -Xmn8m -Xss1m -XX:ReservedCodeCacheSize=5m -XX:NewRatio=3 -jar /usr/local/agent/agent-1.0.1.jar $POOL_TYPE
fi

Using the --init flag

  1. Now that docker 1.13 has added a --init flag, is this a good way to use tini now?
  2. It looks like it will automatically add (tini version 0.13.0 - git.949e6fa) as /dev/init for you. Does this mean there is no need to download tini anymore?
  3. Which method do you suggest as the "preferred method"?

`Exec` as unprivileged user

I think it would be useful to allow execing the process in tini as an unprivileged user, and I'm willing to contribute a patch to enable this behavior. I am dealing with a service that handles permissions as described below and this change would be necessary for my adoption of tini in the Docker context.

My issue is that I have a service that does not require root privileges and does not expect to be execed as root. This service creates a user with a nologin shell when installed by a package manager. This change would allow the service to still access the file system with the appropriate user permissions without having to modify the packaging to support login for the given user.

Foward signals to all child (and adopted) processes

Hi,

Thank you for tini !

During my tests with Docker, I noticed tini:

  • starts the process given as the argument as the "first child"
  • forwards received signals to the "first child" only (or the sub-process branch if -g is used)
  • returns the exit code of the "first child"

In the case where some process has been orphaned and adopted by tini, is it possible to make tini forward signals to these running child processes as well ?

I noticed on an Ubuntu VM, that traditional init seems to ask "all remaining processes to terminate" by sending SIGTERM. I'd like to reproduce this behaviour in order to gracefully stop every child process, even adopted ones.

Thank you for your help.

Unable to build for amd64 machine

I am building tini on amd64 machine
My go env as follow:
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/ravi/gopath"
GORACE=""
GOROOT="/usr/lib/go-1.6"
GOTOOLDIR="/usr/lib/go-1.6/pkg/tool/linux_amd64"
GO15VENDOREXPERIMENT="1"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"

on executing command
$sudo ./ci/install_deps.sh
[sudo] password for test:

  • DEPS=(build-essential git gdb valgrind cmake rpm python-dev libcap-dev python-pip python-virtualenv hardening-includes gnupg)
    ./ci/install_deps.sh: line 12: ARCH_SUFFIX: unbound variable

Can anyone please guide me on this?

Interactive Terminal / TTY Hangup

When using tini with a TTY, interactive shell commands like python and irb hang the terminal. Either of the following Dockerfiles will reproduce the issue (python can be replaced with ruby, etc.):

FROM krallin/ubuntu-tini:trusty
RUN apt-get update && apt-get install -y --no-install-recommends python
FROM debian:8.2

RUN apt-get update && \
    apt-get install -y --no-install-recommends ca-certificates curl libc6 python && \
    curl -sSL "https://github.com/krallin/tini/releases/download/v0.8.0/tini" -o /usr/bin/tini && \
    chmod +x /usr/bin/tini && \
    rm -rf /var/lib/apt/lists/*

ENTRYPOINT ["/usr/bin/tini", "--"]
$ docker build -t tini-tty .
$ docker run --rm -it tini-tty python

Commenting out the ENTRYPOINT and rebuilding the image results in a working TTY session. Non-interactive commands, such as $ docker run --rm -it tini-tty python --version work just fine.

Am I missing something simple here like an option? Thanks!

tini flags and `--`

Because tini has flags the ability to inject init as the init in many containers is not possible without having to change the container. Is there a way that we can remove these options so that this can be a drop in replacement as a container init for something like Docker?

Also would you be interested in having tini the default init for container containers provided by the daemon? I wrote a very similar thing and instead of having two inits I'm interested in using tini instead but the requirement for -- is a deal breaker at the moment and would require changes for what we want to do.

Thanks!

Not compatible with alpine 3.3

Dockerfile:

FROM alpine:3.3
ENV TINI_VERSION v0.9.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini

Command:

ldd /tini

Output:

/lib64/ld-linux-x86-64.so.2 (0x7fe8969b6000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7fe8969b6000)
Error relocating /tini: __fprintf_chk: symbol not found

Unexpected error forwarding signal on Travis-CI

When attempting to spawn a docker container on Travis CI where tini is the entrypoint to the container, I'm seeing:

[FATAL] Unexpected error when forwarding signal: 'Permission denied'

which appears to originate from https://github.com/krallin/tini/blob/master/src/tini.c#L249

Here's an example log from Travis:

I'm not sure if this is a bug in tini or just a constraint of how Travis is executing the containers. Is there some CAP that tini requires that maybe Travis is not allowing? If so, it would be good to document it here.

Ref jupyter-server/kernel_gateway#15

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.