在一个Docker容器中执行命令是否可以关闭宿主机?

15

我有一台主机,上面有一个Docker容器。该容器正在运行一个特定的服务。当满足某个特定条件时,我想删除该容器并关闭主机。这可能吗?我计划修改运行服务的代码以处理关闭主机的操作。欢迎任何建议!


4
带有“privileged”标志的容器,如果需要的话可以直接向相关硬件发出请求来关闭主机。从容器中触发主机关机的任何机制,如果在没有此标志(或运行在主机上的其他代码)的情况下工作,则构成漏洞。 - Charles Duffy
1个回答

29

执行干净的关机将取决于主机的 init 系统。

为了避免给容器授予 --privileged 访问权限,同时也避免在容器中安装主机特定的 init 工具,您可以创建一个接口来向主机发送关机信号,而不是尝试让容器运行关机命令。

一个接口

有很多方法可以实现这个目标。一个简单的起点可能是挂载卷以在容器和主机之间共享数据。现在可以使用文件,但您也可以使用套接字、FIFO、TCP 或您想要的任何其他 IPC 方法。

在主机上创建一个文件,例如 /var/run/shutdown_signal,并将该文件挂载到容器中。

docker run -d -v /var/run/shutdown_signal:/shutdown_signal whatever 

当您想关闭主机时,请将字符串写入文件中。

docker exec $cid sh -c 'echo true > /shutdown_signal'

那么您需要在主机上运行一些东西来监视该文件。

一个使用inotifywait等待文件更改的简单脚本。

echo "waiting" > /var/run/shutdown_signal
while inotifywait -e close_write /var/run/shutdown_signal; do 
  signal=$(cat /var/run/shutdown_signal)
  if [ "$signal" == "true" ]; then 
    echo "done" > /var/run/shutdown_signal
    shutdown -h now
  fi
done

如果 inotifywait 不可用,您可以轮询文件。

while sleep 30; do
  signal=$(cat /var/run/shutdown_signal)
  ...

可怕的替代方案

在Linux中,还有一种更普遍、更根本的方法可以立即触发不干净的关机。

docker run --privileged busybox \
  sh -c 'echo 1 > /proc/sys/kernel/sysrq; echo o > /proc/sysrq-trigger'

但是这可能会给你带来比它的价值更多的问题。


如果整个过程可以更加简洁地从主机完成,那么在容器和主机之间建立接口,并在主机上运行脚本就没有意义了。 - Ricardo Branco
1
@RicardoBranco OP要求从容器中运行的服务中完成此操作。 - Matt
应该告诉OP,如果没有与主机创建接口是不可能实现的。但是,如果有了接口,那么它就毫无意义了,因为所有事情都可以在主机上以正确的方式完成。 - Ricardo Branco
@RicardoBranco 什么是将运行在容器中的服务消息路由到主机以触发容器删除和关闭的正确方法? - Matt
通过向stderr写入并使用docker logs将其发送到主机,或者通过挂载卷的文件进行记录。 - Ricardo Branco
3
“everything could be done in the host anyway” 这句话不是真的。为什么您觉得原帖作者一开始使用容器呢? - Jeanno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接