我有以下 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"]
我的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
IPv6 在虚拟机管理程序上被禁用。
问题是 docker 无法使用 正确停止容器docker stop recursor
。一段时间后,OOMKiller 终止程序并提供以下信息:
Exited (137) 2 seconds ago
我在网上搜索了信号128
+ 9
=137
意味着我没有足够的 RAM,但事实并非如此。当我执行docker exec -it recursor /bin/bash
并尝试终止kill -9 -- 1
容器内的 PID 1 ( ) 时,我没有得到任何反应 - 服务只是继续运行,就好像什么也没发生一样。
我还尝试以守护进程模式启动递归程序 - 相同的结果。
有谁知道为什么会这样?
答案1
PID为1的进程是init进程。这在 pid 命名空间或容器中仍然成立:这个 pid 1 不能被杀死,SIGKILL
因为它没有KILL
定义信号处理程序,与任何其他用户态进程。
如果你真的想杀它,就必须杀它来自主机。在主机上运行(具有足够的权限,可能是root):
kill -KILL $(docker inspect --format '{{.State.Pid}}' containername)
这将关闭整个容器,因为删除其 PID 1 意味着停止容器。请注意,我回答了问题的标题,但没有回答根本问题:导致 OOM 的原因。
更新:可能更容易使用docker kill
,默认为KILL
信号。那将是:
docker kill containername
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
#
没有效果
在第二个终端上:
$ pstree -p $(pidof unshare)
unshare(2023)───bash(2024)
$ kill -9 2024
第一个终端:
# Killed
$