18

As the title indicates, is it possible to restart the host from a container? I have a docker container running with systemd as described here and started as:

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

Once I issue the systemctl reboot command, I see:

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

The host doesn't reboot. However, I see [1915595.016950] systemd-journald[17]: Received SIGTERM from PID 1 (systemd-shutdow). on host's kernel buffer.

Use case:

I am experimenting with running the restraint test harness in a container and some of the tests reboot the host and hence if this is possible to do from a container, the tests can run unchanged.

Update

As I mention in my answer:

There is a detail I missed in my question above which is once I have systemd running in the container itself, the systemctl reboot is (roughly saying) connecting to systemd on the container itself which is not what I want.

The accepted answer has the advantage that it is not dependent on the host and the container distro be have compatible systemd. However, on a setup where they are, my answer is what I think is a more acceptable one, since you can just use the usual reboot command.

Other init systems such as upstart is untested.

4 Answers 4

18

I was able to send sysrq commands to the host mounting /proc/sysrq-trigger as a volume.

This booted the host.

docker-server# docker run -i -t -v /proc/sysrq-trigger:/sysrq centos bash
docker-container# echo b > /sysrq

You can set a bit-mask permission on /proc/sys/kernel/sysrq on the host to only allow eg, sync the disks and boot. More information about this at http://en.wikipedia.org/wiki/Magic_SysRq_key but something like this (untested) should set those permissions:

echo 144 > /proc/sys/kernel/sysrq

Also remember to add kernel.sysrq = 144 to /etc/sysctl.conf to have it saved over reboots.

Sign up to request clarification or add additional context in comments.

5 Comments

Looks promising, thanks! However, for now something which worked for me is posted as answer.
Tested so far: Fedora container on a Fedora host, Ubuntu container on a Fedora host. Accepting this as the answer since, it is not dependent on the container and the host OS init systems to be the same/compatible. Very nice tip!
This might work nicely, but beware that echo b > /sysrq "Will immediately reboot the system without syncing or unmounting your disks." See kernel.org/doc/html/latest/admin-guide/…
@orzechow then you can echo s > /sysrq first
@Softlion exactly!
8

There is a detail I missed in my question above which is once I have systemd running in the container itself, the systemctl reboot is (roughly saying) connecting to systemd on the container itself which is not what I want.

On the hint of a colleague, here is what I did on a "stock" fedora image (nothing special in it):

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

Then in the container:

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

Here, the container is able to access systemd on the host. Then, issuing a reboot command actually reboots the host:

bash-4.2# reboot 

Thus, it is possible to reboot the host from the container.

The point to note here is that the host is running Fedora 20 and so is the container. If the host was a different distro not running systemd, this would not be possible. Generally speaking, if the host and the container are running distros which are not running systemd or incompatible versions of systemd, this will not work.

2 Comments

On Ubuntu 16.04, this works, and so does mounting only /run/dbus. But I have to say, I like 59634's solution more than giving all of dbus to a container. Also, you only need to mount /run/systemd/private. I have no idea how risky this is, but it's less than all of /rub/systemd at least
On Fedora 38 using this method I get System has not been booted with systemd as init system (PID 1). Can't operate. I guess this is out of date.
0

Adding to user59634's answer:

-v /run/systemd:/run/systemd works on fedora 27 and ubuntu 16

But the only socket you need is

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

You can also use /run/dbus, but I like this systemd method more. I do not fully understand how much power you are giving the container, I suspect it is a enough to take over your host. So I would only suggest using this in a container that you wrote, and then communicate with any another container see here.

Unrelated similar information

Sleeping/suspending/hibernating can be done with only the -v /sys/power/state:/sys/power/state, and using /lib/systemd/systemd-sleep suspend for example. If you know how to, you can echo a string directly to /sys/power/state, for example echo mem > /sys/power/state here for more explanation of the different options you get from cat /sys/power/state

Comments

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 container must be granted enough permission to mount /proc

1 Comment

I get "Running in chroot, ignoring request.". does not work.