How to use --init parameter in docker run
Asked Answered
W

2

83

There are --init and --init-path options for docker run, but it's not clear how to use it.

At first, I thought it's something like dumb-init, but included in docker core (kind of "native"). But --init key demands --init-path to be set as well, pointing to docker-init binary, and gives no clue on where to take it. Google is silent about docker-init.

Okay, maybe I'm supposed to use yelp/dumb-init or 'phusion/baseimage-docker', but those solutions don't seem to use docker run's --init option.

So, I'm curious where do I take this "docker-init binary" to set the --init-path to?

Wayfaring answered 30/3, 2017 at 15:24 Comment(3)
Which version are you using? I'm not experiencing this with the latest version.Niggling
Docker version 17.03.1-ce, build c6d412eWayfaring
Readers of this discussion may find the documentation about docker run and --init useful: docs.docker.com/engine/reference/run/#specify-an-init-processFootstalk
S
110

Specifiying the new docker --init option in the run command basically sets ENTRYPOINT to tini and passes the CMD to it or whatever you specify on the commandline.

For example, without init, CMD becomes pid 1. In this case, /bin/bash

docker run -ti --rm ubuntu:16.04 /bin/bash
root@d740f7360840:/# ps -fA
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  1 03:30 ?        00:00:00 /bin/bash
root        11     1  0 03:30 ?        00:00:00 ps -fA

With --init, tini (/dev/init) becomes pid 1

docker run -ti --init --rm ubuntu:16.04 /bin/bash
root@5b5fe6ee71b5:/# ps -fA
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  1 03:30 ?        00:00:00 /dev/init -- /bin/bash
root         7     1  0 03:30 ?        00:00:00 /bin/bash
root        12     7  0 03:30 ?        00:00:00 ps -fA

tini is a first class init process that can be run as pid 1 correctly. A pid 1 process must reap forked child processes correctly, if it doesn't then bad things happen like resources get leaked and zombies appear.

This is what you want for applications that fork and haven't been written with child reaping in mind as normally they would leave this up to the init system. A classic example is java Jenkins applications.

Skerrick answered 22/6, 2017 at 3:37 Comment(6)
Very good points here! I would also recommend to everyone to have a look on this post about tiniThedathedric
So I've got an image with python app installed that has multiple commands and processes to run, webserver, monitor, worker… I made an entry point script which does some setup for each so I can run 3 versions of the image and pass only webserver, monitor, or worker as the command. The entry point handles a little bit of initialization for the webserver that differs from the others. I do get some zombie processes though if a gunicorn worker dies; I've been wondering if I can throw in --init and keep the entry point and command as is.Blaseio
@Blaseio it seems to be possible; see the documentation of Tini here: github.com/krallin/tini#existing-entrypointVeradia
@Apteryx; I actually wonder if using docker's --init will change the entrypoint to be prefixed by tini as tini docs suggest it should be, or if it leaves the entrypoint as is but then runs it with tini (effectively the same thing but different metadata on the image), or if it replaces the entrypoint with tini (which is what the docker docs seem to say).Blaseio
@Blaseio looking at the PR for the --init feature (github.com/moby/moby/pull/26061/…), what the implementation does (in the populateCommonSpecs procedure of the oci_linux.go module) is: prefix any program and args that would have been executed with "/dev/init", which is bind-mounted to the binary of Tini. My guess is that the metadata is untouched, as this populateCommonSpecs command's purpose seems to be to initialize the base file system of the container.Veradia
One thing that I found misleading in this answer is that using --init doesn't actually set the entrypoint in the container metadata (i.e. if there is no ENTRYPOINT in the Dockerfile, and you use --init, the entrypoint field in docker inspect will still be null). What it does is setting the key HostConfig.Init to true. The docker-init binary (specified with init-path), is bind mounted as /dev/init in the container. When that key is set, /dev/init is prepended to the user's command args. Tested on docker 18.06.Crumpled
W
11

I've found this in documentation:

You can use the --init flag to indicate that an init process should be used as the PID 1 in the container. Specifying an init process ensures the usual responsibilities of an init system, such as reaping zombie processes, are performed inside the created container. The default init process used is the first docker-init executable found in the system path of the Docker daemon process. This docker-init binary, included in the default installation, is backed by tini.

I couldn't find docker-init on a macOS Docker installation, but on Linux it's here:

/usr/bin/docker-init

Wayfaring answered 30/3, 2017 at 20:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.