├── .gitattributes ├── .gitignore ├── Dockerfile ├── setup ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.swo 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | ENV container docker 4 | 5 | # Don't start any optional services except for the few we need. 6 | RUN find /etc/systemd/system \ 7 | /lib/systemd/system \ 8 | -path '*.wants/*' \ 9 | -not -name '*journald*' \ 10 | -not -name '*systemd-tmpfiles*' \ 11 | -not -name '*systemd-user-sessions*' \ 12 | -exec rm \{} \; 13 | 14 | RUN apt-get update && \ 15 | apt-get install -y \ 16 | dbus && \ 17 | apt-get clean && \ 18 | rm -rf /var/lib/apt/lists/* 19 | 20 | RUN systemctl set-default multi-user.target 21 | 22 | COPY setup /sbin/ 23 | 24 | STOPSIGNAL SIGRTMIN+3 25 | 26 | # Workaround for docker/docker#27202, technique based on comments from docker/docker#9212 27 | CMD ["/bin/bash", "-c", "exec /sbin/init --log-target=journal 3>&1"] 28 | -------------------------------------------------------------------------------- /setup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu 3 | 4 | if nsenter --mount=/host/proc/1/ns/mnt -- mount | grep /sys/fs/cgroup/systemd >/dev/null 2>&1; then 5 | echo 'The systemd cgroup hierarchy is already mounted at /sys/fs/cgroup/systemd.' 6 | else 7 | if [ -d /host/sys/fs/cgroup/systemd ]; then 8 | echo 'The mount point for the systemd cgroup hierarchy already exists at /sys/fs/cgroup/systemd.' 9 | else 10 | echo 'Creating the mount point for the systemd cgroup hierarchy at /sys/fs/cgroup/systemd.' 11 | mkdir -p /host/sys/fs/cgroup/systemd 12 | fi 13 | 14 | echo 'Mounting the systemd cgroup hierarchy.' 15 | nsenter --mount=/host/proc/1/ns/mnt -- mount -t cgroup cgroup -o none,name=systemd /sys/fs/cgroup/systemd 16 | fi 17 | echo 'Your Docker host is now configured for running systemd containers!' 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Solita 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PROJECT UNMAINTAINED 2 | 3 | **This image is no longer used nor maintained by its original developer. If you 4 | want to continue its development, you may fork the project in accordance with 5 | [its license](LICENSE).** 6 | 7 | ------------------------------------------------------------------------------- 8 | 9 | # solita/ubuntu-systemd 10 | 11 | A Docker image based on `ubuntu` that runs `systemd` with a minimal set of 12 | services. 13 | 14 | **This image is meant for development use only. We strongly recommend against 15 | running it in production!** 16 | 17 | ## Supported tags 18 | 19 | * `18.04`, `bionic` 20 | * `16.04`, `xenial`, `latest` 21 | 22 | ## But why? 23 | 24 | The short answer: use `solita/ubuntu-systemd` for running applications that 25 | need to be run in a full Ubuntu system and not on their own as PID 1. 26 | 27 | The long answer: `solita/ubuntu-systemd` might be a better choice than the 28 | stock `ubuntu` image if one of the following is true: 29 | 30 | - You want to test a provisioning or deployment script that configures and 31 | starts `systemd` services. 32 | 33 | - You want to run multiple services in the same container. 34 | 35 | - You want to solve the [the PID 1 zombie reaping problem](https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/). 36 | 37 | If you just want to run a single, short-lived process in a container, you 38 | should probably use the stock `ubuntu` image instead. 39 | 40 | ## Setup 41 | 42 | Before you start your first `systemd` container, run the following command to 43 | set up your Docker host. It uses [special privileges](https://docs.docker.com/engine/reference/run/#/runtime-privilege-and-linux-capabilities) 44 | to create a cgroup hierarchy for `systemd`. We do this in a separate setup 45 | step so we can run `systemd` in unprivileged containers. 46 | 47 | docker run --rm --privileged -v /:/host solita/ubuntu-systemd setup 48 | 49 | ## Running 50 | 51 | You need to add a couple of flags to the `docker run` command to make `systemd` 52 | play nice with Docker. 53 | 54 | We must disable seccomp because `systemd` uses system calls that are not 55 | allowed by Docker's default seccomp profile: 56 | 57 | --security-opt seccomp=unconfined 58 | 59 | Ubuntu's `systemd` expects `/run` and `/run/lock` to be `tmpfs` file systems, 60 | but it can't mount them itself in an unprivileged container: 61 | 62 | --tmpfs /run 63 | --tmpfs /run/lock 64 | 65 | `systemd` needs read-only access to the kernel's cgroup hierarchies: 66 | 67 | -v /sys/fs/cgroup:/sys/fs/cgroup:ro 68 | 69 | Allocating a pseudo-TTY is not strictly necessary, but it gives us pretty 70 | color-coded logs that we can look at with `docker logs`: 71 | 72 | -t 73 | 74 | ## Testing 75 | 76 | This image is useless as it's only meant to serve as a base for your own 77 | images, but you can still create a container from it. First set up your Docker 78 | host as described in Setup above. Then run the following command: 79 | 80 | docker run -d --name systemd --security-opt seccomp=unconfined --tmpfs /run --tmpfs /run/lock -v /sys/fs/cgroup:/sys/fs/cgroup:ro -t solita/ubuntu-systemd 81 | 82 | Check the logs to see if `systemd` started correctly: 83 | 84 | docker logs systemd 85 | 86 | If everything worked, the output should look like this: 87 | 88 | systemd 229 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ -LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD -IDN) 89 | Detected virtualization docker. 90 | Detected architecture x86-64. 91 | 92 | Welcome to Ubuntu 16.04.2 LTS! 93 | 94 | Set hostname to . 95 | Initializing machine ID from random generator. 96 | [ OK ] Created slice System Slice. 97 | [ OK ] Reached target Slices. 98 | [ OK ] Listening on Journal Socket. 99 | [ OK ] Listening on Journal Socket (/dev/log). 100 | [ OK ] Reached target Local File Systems. 101 | Starting Journal Service... 102 | Starting Create Volatile Files and Directories... 103 | [ OK ] Reached target Swap. 104 | [ OK ] Reached target Sockets. 105 | [ OK ] Reached target Paths. 106 | [ OK ] Started Create Volatile Files and Directories. 107 | [ OK ] Started Journal Service. 108 | 109 | Also check the journal logs: 110 | 111 | docker exec systemd journalctl 112 | 113 | The output should look like this: 114 | 115 | -- Logs begin at Thu 2017-03-16 14:12:14 UTC, end at Thu 2017-03-16 14:12:26 UTC. -- 116 | Mar 16 14:12:14 aad1d41c3a2e systemd-journald[19]: Runtime journal (/run/log/journal/) is 8.0M, max 99.9M, 91.9M free. 117 | Mar 16 14:12:14 aad1d41c3a2e systemd-journald[19]: Journal started 118 | Mar 16 14:12:14 aad1d41c3a2e systemd[1]: Reached target System Initialization. 119 | Mar 16 14:12:15 aad1d41c3a2e systemd[1]: Reached target Basic System. 120 | Mar 16 14:12:17 aad1d41c3a2e systemd[1]: Starting LSB: Set the CPU Frequency Scaling governor to "ondemand"... 121 | Mar 16 14:12:18 aad1d41c3a2e systemd[1]: Starting Permit User Sessions... 122 | Mar 16 14:12:19 aad1d41c3a2e systemd[1]: Starting /etc/rc.local Compatibility... 123 | Mar 16 14:12:20 aad1d41c3a2e systemd[1]: Started Daily Cleanup of Temporary Directories. 124 | Mar 16 14:12:21 aad1d41c3a2e systemd[1]: Reached target Timers. 125 | Mar 16 14:12:22 aad1d41c3a2e systemd[1]: Started Permit User Sessions. 126 | Mar 16 14:12:23 aad1d41c3a2e systemd[1]: Started /etc/rc.local Compatibility. 127 | Mar 16 14:12:24 aad1d41c3a2e systemd[1]: Started LSB: Set the CPU Frequency Scaling governor to "ondemand". 128 | Mar 16 14:12:25 aad1d41c3a2e systemd[1]: Reached target Multi-User System. 129 | Mar 16 14:12:26 aad1d41c3a2e systemd[1]: Startup finished in 11.215s. 130 | 131 | To check for clean shutdown, in one terminal run: 132 | 133 | docker exec systemd journalctl -f 134 | 135 | And in another shut down `systemd`: 136 | 137 | docker stop systemd 138 | 139 | The journalctl logs should look like this on a clean shutdown: 140 | 141 | Mar 16 14:15:49 aad1d41c3a2e systemd[1]: Received SIGRTMIN+3. 142 | Mar 16 14:15:49 aad1d41c3a2e systemd[1]: Stopped target Multi-User System. 143 | Mar 16 14:15:50 aad1d41c3a2e systemd[1]: Stopping Permit User Sessions... 144 | Mar 16 14:15:51 aad1d41c3a2e systemd[1]: Stopping LSB: Set the CPU Frequency Scaling governor to "ondemand"... 145 | Mar 16 14:15:52 aad1d41c3a2e systemd[1]: Stopped /etc/rc.local Compatibility. 146 | Mar 16 14:15:53 aad1d41c3a2e systemd[1]: Stopped target Timers. 147 | Mar 16 14:15:54 aad1d41c3a2e systemd[1]: Stopped Daily Cleanup of Temporary Directories. 148 | Mar 16 14:15:55 aad1d41c3a2e systemd[1]: Stopped Permit User Sessions. 149 | Mar 16 14:15:56 aad1d41c3a2e systemd[1]: Stopped LSB: Set the CPU Frequency Scaling governor to "ondemand". 150 | Mar 16 14:15:57 aad1d41c3a2e systemd[1]: Stopped target Basic System. 151 | Mar 16 14:15:58 aad1d41c3a2e systemd[1]: Stopped target Slices. 152 | 153 | ## Known issues 154 | 155 | There's [a bug](https://github.com/docker/docker/issues/22327) in Docker 156 | versions < 1.12.0 that randomly causes `/run` and `/run/lock` to be mounted in 157 | the wrong order. In this case the output of `docker logs` looks like this: 158 | 159 | Failed to mount tmpfs at /run/lock: Permission denied 160 | [!!!!!!] Failed to mount API filesystems, freezing. 161 | Freezing execution. 162 | 163 | If this happens to you, `docker kill` the container (it won't listen for the 164 | shutdown signal) and start it again with `docker start`. Better luck next time! 165 | 166 | ## Contributors 167 | 168 | * [Timo Mihaljov](https://github.com/noidi) 169 | * [Andrew Wason](https://github.com/rectalogic) 170 | * [Damian ONeill](https://github.com/damianoneill) 171 | * [Jeroen Vermeulen](https://github.com/jeroenvermeulen) 172 | 173 | ## License 174 | 175 | Copyright © 2016-2018 [Solita](http://www.solita.fi). Licensed under [the MIT license](https://github.com/solita/docker-systemd/blob/master/LICENSE). 176 | --------------------------------------------------------------------------------