7

I would like to shutdown the machine (host) when the docker container finishes a job.

My host OS is Ubuntu.

The container can run as --privileged=true. That is not a problem.

I managed to do this with the command (found in a stackoverflow answer):

subprocess.run("echo 1 > /proc/sys/kernel/sysrq; echo o > /proc/sysrq-trigger", shell=True, check=True)

The problem with this approach it is immediate, unclean shutdown in Linux.

If I try a clean way as a shutdown now, I get the following error: System has not been booted with systemd as init system (PID 1). Can't operate.

How can I use shutdown or halt or other alternative within my container to shutdown the host?

  • You don't need a subprocess and a shell to open two pseudofiles and write to them. – tripleee Aug 06 '20 at 13:55
  • `with open('/proc/sys/kernel/sysrq', 'w') as sysrq, open('/proc/sysrq-trigger') as trigger: sysrq.write('1\n'); trigger.write('o\n')` – tripleee Aug 06 '20 at 14:02

2 Answers2

7

For your specific case to perform a shutdown once the docker exits mikey's solution is simple and elegant.

For a more generic case, like with a bunch of dockerized micro-services with one needing to be able to shut down or reboot the host, the following approach can be used:

In systemd systems like recent Debian or Ubuntu, the shutdown/halt/poweroff/reboot commands are just symlinks to systemctl and it is possible to run for example systemctl halt instead of just halt.

So the issue becomes to perform systemctl commands on the host from within a docker container. This can be achieved mapping some volumes like in the following command:

docker run -it --rm -v /bin/systemctl:/bin/systemctl -v /run/systemd/system:/run/systemd/system -v /var/run/dbus/system_bus_socket:/var/run/dbus/system_bus_socket -v /sys/fs/cgroup:/sys/fs/cgroup debian:10 systemctl --no-pager status

With these volumes mapped, you can then just execute a systemctl poweroff from within the docker and the host will shut down and power off.

Martin
  • 451
  • 6
  • 10
  • 4
    The example command in my case returns `Failed to read server status: Access denied` unless I add `--privileged`. – jbvo Jan 27 '21 at 15:02
  • 1
    That's well possible. In my case i didn't need `--privileged`, tried it both running root or an user inside the container. To be honest i was surprised it worked withoug it. But probably on many systems it is needed. – Martin Jan 27 '21 at 15:55
  • 1
    Hah I love it, that's really cool. Have you had to expose the host systemd to containers before? – mikey Jan 28 '21 at 08:25
  • 1
    No, it's the first time. – Martin Jan 28 '21 at 12:57
  • Works perfectly for me with `--privileged`. Allows me to reboot the host machine from the Portainer web interface, which means I don't need an open SSH connection to my server (or to hook up a keyboard and monitor). – ndm13 Jul 12 '22 at 00:13
3

Unless I'm missing an unspecified constraint, I can't see why you couldn't do this on the host from a shell:

  • docker run image_name; shutdown now

This would required the Dockerfile to end in a CMD or ENTRYPOINT command, which specifies the script.

Once the script within the container finishes, the docker run process will end, and the shell can move onto the next command which is shutdown now.

mikey
  • 1,068
  • 10
  • 13