从Docker容器重新启动主机

14

如标题所示,从一个容器中重启主机是否可能?我有一个使用systemd运行的Docker容器,可以在这里查看说明,并按以下方式启动:

$ docker run -privileged --net host -ti -d -v /sys/fs/cgroup:/sys/fs/cgroup:ro <image_name>

一旦我执行了systemctl reboot命令,我会看到:

# systemctl reboot
[root@dhcp-40-115 /]# 
[3]+  Stopped   

主机不重新启动。但是我在主机的内核缓冲区中看到 [1915595.016950] systemd-journald[17]: Received SIGTERM from PID 1 (systemd-shutdow).

使用案例:

我正在尝试在容器中运行restraint测试工具,其中一些测试会重启主机。因此,如果可以从容器中进行操作,则可以无需更改测试即可运行。

更新

正如我在答案中提到的:

  

我在上面的问题中错过了一个细节,那就是一旦我在容器本身中运行systemd,systemctl reboot就会(粗略地说)连接到容器本身上的systemd,这不是我想要的。

接受的答案有一个优点,它不依赖于主机和容器发行版是否具有兼容的systemd。但是,在它们兼容时,我认为我的答案是更可接受的,因为您可以使用常规的reboot命令。

其他初始化系统,如upstart未经测试。

4个回答

15
我能够通过挂载/proc/sysrq-trigger作为卷来向主机发送sysrq命令。这使得主机启动了。
docker-server# docker run -i -t -v /proc/sysrq-trigger:/sysrq centos bash
docker-container# echo b > /sysrq

您可以在主机上的/proc/sys/kernel/sysrq上设置位掩码权限,以仅允许例如同步磁盘和引导。有关更多信息,请参见http://en.wikipedia.org/wiki/Magic_SysRq_key,但类似这样(未经测试)的内容应设置这些权限:
echo 144 > /proc/sys/kernel/sysrq

同时记得将kernel.sysrq = 144添加到/etc/sysctl.conf中,以便在重启后保存。


看起来很有前途,谢谢!不过,目前对我有效的是已发布为答案的内容。 - user59634
到目前为止已经测试了:在 Fedora 主机上的 Fedora 容器,以及在 Fedora 主机上的 Ubuntu 容器。接受这个答案,因为它不依赖于容器和主机操作系统的 init 系统是否相同/兼容。非常好的提示! - user59634
这个可能很有效,但要小心echo b > /sysrq会立即重新启动系统,而不会同步或卸载您的磁盘。请参阅https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html#what-are-the-command-keys。 - undefined

8

在我上面的问题中,我忽略了一个细节,即一旦我在容器本身中运行systemdsystemctl reboot(粗略地说)连接到容器本身上的systemd,这不是我想要的。

在同事的提示下,在“原始”的Fedora镜像上执行以下操作:

$ docker run -ti -v /run/systemd:/run/systemd fedora /bin/bash

然后在容器中:

bash-4.2# systemctl status docker
docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled)
   Active: active (running) since Tue 2014-07-01 04:57:22 UTC; 2 weeks 0 days ago
     Docs: http://docs.docker.io
 Main PID: 2589
   CGroup: /system.slice/docker.service

在这里,容器能够访问主机上的 systemd。然后,发出 reboot 命令实际上会重新启动主机:

bash-4.2# reboot 

因此,可以从容器重新启动主机。
需要注意的是,主机正在运行Fedora 20,容器也是如此。如果主机是不运行systemd的其他发行版,则不可能实现这一点。一般来说,如果主机和容器运行的发行版不运行systemd或不兼容systemd的版本,则无法使用此功能。

1
在Ubuntu 16.04上,这个可以工作,只挂载/run/dbus也是可以的。但我必须说,我更喜欢59634的解决方案,而不是将整个dbus都给容器。此外,你只需要挂载/run/systemd/private。我不知道这有多大风险,但至少比挂载整个/run/systemd要少。 - Andy
在Fedora 38上使用这种方法,我得到了系统未使用systemd作为init系统(PID 1)启动。无法操作。我猜这是过时的。 - undefined

0

补充user59634的答案:

-v /run/systemd:/run/systemd 在fedora 27和ubuntu 16上有效。

但你只需要一个socket:

docker run -it --rm -v /run/systemd/private:/run/systemd/private fedora reboot

你也可以使用/run/dbus,但我更喜欢这种systemd方法。我不完全理解你给容器提供了多少权限,我怀疑它足以接管你的主机。因此,我建议仅在你编写的容器中使用它,并与任何其他容器通信,请参见here

无关的类似信息

休眠/暂停/休眠模式只需要使用-v /sys/power/state:/sys/power/state,例如使用/lib/systemd/systemd-sleep suspend。如果您知道如何操作,可以直接向/sys/power/state发出字符串,例如echo mem > /sys/power/state在这里了解更多关于从cat /sys/power/state获取不同选项的说明。

0
docker run -d --name network_monitor --net host --restart always --privileged --security-opt apparmor=unconfined  --cap-add=SYS_ADMIN \
-v /proc:/proc \
$IMAGE_URI

docker容器必须被授予足够的权限来挂载/proc


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