How to shutdown the host (ubuntu) inside a docker container

11k Views Asked by At

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?

2

There are 2 best solutions below

5
On

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.

0
On

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.