projectatomic / oci-systemd-hook

OCI hook to enable running systemd in a container
GNU General Public License v3.0
64 stars 26 forks source link

OCI systemd hooks

OCI systemd hook enables users to run systemd in docker and OCI compatible runtimes such as runc without requiring --privileged flag.

This project produces a C binary that can be used with runc and Docker (with minor code changes). If you clone this branch and build/install oci-systemd-hook, a binary should be placed in /usr/libexec/oci/hooks.d named oci-systemd-hook.

Running Docker or OCI runc containers with this executable, oci-systemd-hook is called just before a container is started and after it is provisioned. If the CMD to run inside of the container is init or systemd, this hook will configure the container image to run a systemd environment. For all other CMD's, this hook will just exit.

When oci-systemd-hook detects systemd inside of the container it does the following:

When the container stops, these file systems will be umounted.

systemd is expected to be able to run within the container without requiring the --privileged option. However you will still need to specify a special --stop-signal. Standard docker containers sends SIGTERM to pid 1, but systemd does not shut down properly when it recieves a SIGTERM. systemd specified that it needs to receive a RTMIN+3 signal to shutdown properly.

Usage

If you created a container image based on a Dockerfile like the following:

cat Dockerfile
FROM fedora:latest
ENV container docker
RUN yum -y update && yum -y install httpd && yum clean all
RUN systemctl mask dnf-makecache.timer && systemctl enable httpd
CMD [ "/sbin/init" ]

(The systemctl mask dnf-makecache.timer is a workaround for a container base image bug)

You should then be able to execute the following commands:

docker build -t httpd .
docker run -ti --stop-signal=RTMIN+3 httpd

If you run this hook along with oci-register-machine oci hook, you will be able to show the container's journal information on the host, using journalctl.

journalctl -M CONTAINER_UUID

To use this directly with runc, modify or add the following to config.json.

    "hooks": {
        "prestart": [
            {
                "path": "/usr/libexec/oci/hooks.d/oci-systemd-hook"
            }
        ]
    },
...
    "process": {
        "capabilities": {
...
                "CAP_AUDIT_WRITE",
                "CAP_KILL",
                "CAP_NET_BIND_SERVICE",
                "CAP_MKNOD",
                "CAP_CHOWN",
                "CAP_DAC_OVERRIDE",
                "CAP_FSETID",
                "CAP_FOWNER",
                "CAP_NET_RAW",
                "CAP_SETGID",
                "CAP_SETUID",
                "CAP_SETFCAP",
                "CAP_SETPCAP",
                "CAP_SYS_CHROOT"
...
        "env": [
            "container=oci",

Disabling oci-systemd-hook

To disable oci-systemd-hook for a particular run, which is primarily useful in an Atomic Host environment, the environment variable 'oci-systemd-hook' can be set to 'disabled'. This prevents oci-systemd-hook from being run for that invocation. A sample usage is:

docker run --env oci-systemd-hook=disabled -it --rm  fedora /bin/bash

To build and install

Prior to installing oci-systemd-hook, install the following packages on your linux distro:

In Fedora, you can use this command:

 yum -y install \
    autoconf \
    automake \
    gcc \
    git \
    go-md2man \
    libmount-devel \
    libselinux-devel \
    yajl-devel

Then clone this branch and follow these steps:

git clone https://github.com/projectatomic/oci-systemd-hook
cd oci-systemd-hook
autoreconf -i
./configure --libexecdir=/usr/libexec/oci/hooks.d
make
make install