无法在 docker 容器中使用 PID 1 终止进程

man*_*tor 13 process kill debian docker

我有以下 Dockerfile 用于创建一个包含 powerdns 递归的容器:

FROM debian:stretch-slim
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && \
    apt-get install --no-install-recommends -y \
    pdns-recursor && \
    rm -rf /var/lib/apt/lists/* && \
    apt-get clean
COPY ./configuration/recursor.conf /etc/powerdns/recursor.conf
RUN chown -R :pdns /etc/powerdns/ && \
    chmod 0750 /etc/powerdns/ && \
    chmod 0640 /etc/powerdns/recursor.conf
EXPOSE 8699
ENTRYPOINT ["/usr/sbin/pdns_recursor", "--daemon=no"]
Run Code Online (Sandbox Code Playgroud)

我的recursor.conf看起来像这样:

config-dir=/etc/powerdns
forward-zones=resolver1.opendns.com=208.67.222.222
hint-file=/usr/share/dns/root.hints
local-address=0.0.0.0
local-port=8699
quiet=yes
security-poll-suffix=
setgid=pdns
setuid=pdns
Run Code Online (Sandbox Code Playgroud)

虚拟机管理程序上禁用了 IPv6。

问题是 docker 无法使用docker stop recursor. 一段时间后,OOMKiller 使用以下信息终止程序:

Exited (137) 2 seconds ago
Run Code Online (Sandbox Code Playgroud)

我在网上搜索,信号128+ 9=137表示我没有足够的 RAM,事实并非如此。当我执行docker exec -it recursor /bin/bash并尝试杀死kill -9 -- 1容器内的PID 1 ( ) 时,我没有得到任何反应 - 该服务只是继续运行,就好像什么也没发生一样。

我还尝试在守护进程模式下启动递归 - 结果相同。

有谁知道为什么会这样?

A.B*_*A.B 20

PID 为 1 的进程是 init 进程。这在 pid 命名空间或容器中仍然成立:这个 pid 1 不能被杀死,SIGKILL因为它没有KILL定义信号处理程序,这与任何其他用户态进程相反。

如果你真的想杀死它,你必须从宿主那里杀死它。在主机上运行(有足够的权限,可能是 root):

kill -KILL $(docker inspect --format '{{.State.Pid}}' containername)
Run Code Online (Sandbox Code Playgroud)

这将关闭整个容器,因为删除其 PID 1 意味着停止容器。请注意,我回答了问题的标题,但没有回答潜在的问题:是什么导致了 OOM。

更新:使用可能更简单docker kill,默认为KILL信号。那将是:

docker kill containername
Run Code Online (Sandbox Code Playgroud)

UPDATE2:说服 PID 1 不能被SIGKILL(又名-9)杀死,即使在容器中也是如此(该示例需要启用用户命名空间,否则仅unshare --mount-proc --fork --pid作为 root使用)。

第一个终端:

$ unshare --map-root-user --mount-proc --fork --pid
# echo $$
1
# pstree -p
bash(1)---pstree(88)
# kill -9 1
#
Run Code Online (Sandbox Code Playgroud)

没有效果

在第二个终端上:

$ pstree -p $(pidof unshare)
unshare(2023)???bash(2024)
$ kill -9 2024
Run Code Online (Sandbox Code Playgroud)

第一个终端:

# Killed
$ 
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你,但我不会同意这一点。我可以杀死容器中的其他容器,发出 `kill -- 1` (PID 1),它们会立即停止。另外,当我从外部发出“docker stop container”时,它们会立即停止。我知道粗略的“dockerkillcontainer”,并且我知道我可以使用他的PID从主机上杀死他,但这不是问题的关键。 (2认同)