I have seen many workarounds for this to run systemd inside docker containers but looks like most of them compromise the security of the container and the host. How are most people here dealing with running systemd specific stuff inside the container.
You didn't mention what distribution you're using inside your container (which would have implications w/r/t which version of systemd you're using), but the following will successfully boot a CentOS container running systemd:
docker run -it --rm \ -e container=docker \ --tmpfs /run \ --tmpfs /tmp \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ --cap-add SYS_ADMIN \ centos /sbin/init
This is with Docker 17.05.0-ce; older versions may require additional flags. Using a stock
centos:7 image, your initial environment inside the container looks like this:
# systemctl status State: running Jobs: 0 queued Failed: 0 units Since: Mon 2017-12-04 17:47:15 UTC; 45s ago [...]
# ps -fe UID PID PPID C STIME TTY TIME CMD root 1 0 0 17:47 ? 00:00:00 /sbin/init root 16 1 0 17:47 ? 00:00:00 /usr/lib/systemd/systemd-journald dbus 26 1 0 17:47 ? 00:00:00 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation root 28 1 0 17:47 ? 00:00:00 /usr/lib/systemd/systemd-logind root 30 1 0 17:47 console 00:00:00 /sbin/agetty --noclear --keep-baud console 115200 38400 9600 vt220 root 32 0 0 17:47 ? 00:00:00 bash root 58 32 0 17:48 ? 00:00:00 ps -fe
Note that I'm using
--rm here not because it's necessary but because I'm terrible at cleaning things up after the fact. It's not necessary to get the container to run.
but looks like most of them compromise the security of the container and the host
Well, running systemd does require privileges beyond those granted to a typical Docker container (hence the
--cap-add). Whether this has security implications for your environment or not depends on what you're doing.
For example, if you want to run systemd in a Arch Linux container,
run this command:
docker run -it --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro --name=ArchLinux archlinux /bin/sh -c "if [ -x /etc/docker-start ]; then exec /etc/docker-start; else exec /bin/sh; fi"
Then run these commands in the container:
echo 'Server = https://THE_FASTEST_MIRROR_FOR_YOU/archlinux/$repo/os/$arch' >/etc/pacman.d/mirrorlist pacman -Sy --noconfirm systemd systemd-sysvcompat passwd -d root echo -en '#!/bin/sh\numount /etc/hostname; umount /etc/hosts; umount /etc/resolv.conf; exec /usr/lib/systemd/systemd' >/etc/docker-start chmod 700 /etc/docker-start echo -e 'nameserver 184.108.40.206' >/etc/resolv.conf exit
Then start the container and attach to it:
docker start -ia ArchLinux
You need to run with
--privileged, and this may cause some security problems. Please try to avoid it if possible.
According to this blog, it is possible to run systemd inside a docker container by building the following dockerfile:
FROM fedora:rawhide MAINTAINER "Dan Walsh" <firstname.lastname@example.org> ENV container docker RUN yum -y update; yum clean all RUN yum -y install systemd; yum clean all; (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); rm -f /lib/systemd/system/multi-user.target.wants/*; rm -f /etc/systemd/system/*.wants/*; rm -f /lib/systemd/system/local-fs.target.wants/*; rm -f /lib/systemd/system/sockets.target.wants/*udev*; rm -f /lib/systemd/system/sockets.target.wants/*initctl*; rm -f /lib/systemd/system/basic.target.wants/*; rm -f /lib/systemd/system/anaconda.target.wants/*; VOLUME [ "/sys/fs/cgroup" ] CMD ["/usr/sbin/init"]
using this command:
docker build -t httpd_rawhide .
The author indicates that the built docker image could be used as a base image
FROM systemd_rawhide RUN yum -y install httpd; yum clean all; systemctl enable httpd.service EXPOSE 80 CMD ["/usr/sbin/init"]
and if the container is run
docker run –privileged -ti -v /sys/fs/cgroup:/sys/fs/cgroup:ro -p 80:80 httpd_rawhide
systemd will run inside the docker container. It is also possible to run multiple services using systemd. According to the creator of this blog it would be possible to run both mariadb and http inside the same container.
Based on this blog and other articles I read my conclusion is that it is technically possible to run systemd inside a docker container, but I would recommend to avoid running systemd inside a container.
First of all, if systemd is able to run inside a container then this means that it is possible to run multiple services like the author did. From a docker perspective this is not recommended as docker is meant to scale horizontally, i.e. if the load increases of http then addtional docker images should be started.
Second, if such a systemd container will be deployed on an orchestration platform like docker swarm. Will that work? I have some doubts whether that will work.
Third, Running systemd by mounting the cgroup in a privileged container does not look very secure.
In conclusion, although you indicated that the script requires systemd, either rewrite the code or use something else. Running systemd inside a docker container should be avoided in my opinion.