如何在docker run中使用--init参数

Mik*_*sin 42 docker

--init--init-path选项docker run,但不清楚如何使用它.

起初,我认为它类似于dumb-init,但包含在docker core(有点像"native")中.但--init关键要求--init-path也要设置,指向'docker-init binary',并且不知道从哪里拿它.谷歌对"docker-init"保持沉默.

好吧,也许我应该使用'yelp/dumb-init'或'phusion/baseimage-docker',但这些解决方案似乎没有使用docker run--init选项.

所以,我很好奇我在哪里把这个"docker-init二进制"设置--init-path为?

Mat*_*att 54

在run命令中指定新的docker --init选项基本上将ENTRYPOINT设置为tini并将CMD传递给它或您在命令行上指定的任何内容.

例如,在没有init的情况下,CMD变为pid 1.在这种情况下,/ 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
Run Code Online (Sandbox Code Playgroud)

使用--init,tini(/ dev/init)变为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
Run Code Online (Sandbox Code Playgroud)

tini是一个可以正确运行为pid 1的第一类init进程.一个pid 1进程必须正确地收集分叉的子进程,如果没有,那么就会发生诸如资源泄露和僵尸出现之类的坏事.

这就是你想要的那些应用程序,这些应用程序是fork并且没有用子进行编写的,因为通常他们会把它留给init系统.一个典型的例子是java Jenkins应用程序.

  • 这里非常好!我还建议大家看一下关于蒂尼的这篇文章(https://github.com/krallin/tini/issues/8#issuecomment-146135930) (2认同)
  • 我在这个答案中发现误导的一件事是,使用 `--init` 实际上并没有在容器元数据中设置入口点(即,如果 Dockerfile 中没有 ENTRYPOINT,并且您使用 `--init`,则入口点`docker Inspect` 中的字段仍然为空)。它的作用是将键“HostConfig.Init”设置为“true”。docker-init 二进制文件(使用 init-path 指定)在容器中绑定安装为“/dev/init”。设置该键后,`/dev/init` 将被添加到用户的命令参数之前。在 docker 18.06 上测试。 (2认同)

Mik*_*sin 5

我在文档中发现了这个:

您可以使用--init标志指示应将init进程用作容器中的PID 1.指定init进程可确保在创建的容器内执行init系统的常规职责,例如收获僵尸进程.使用的默认init进程是Docker守护程序进程的系统路径中找到的第一个docker-init可执行文件.这个docker-init二进制文件包含在默认安装中,由tini支持 .

docker-init在macOS Docker安装上找不到,但在Linux上它就在这里:

/usr/bin/docker-init