cgroup v2 環境において Docker コンテナ内で systemd を起動するときの注意点

この記事は [Z Lab Advent Calendar 2021](https://qiita.com/advent-calendar/2021/zlab) の11日目の記事となります。

## 2022-06-07 追記

> ここまで調べて何気なく Docker Desktop のリリースノートを眺めていたら、以下の記載から、やはり cgroup v2 環境では CentOS 7 の systemd container を動かせないようです。どうにかして動かすことができるのかもしれませんが、今回はそこまで深堀りはしませんでした。

当時は深堀りしませんでしたが、以下を参考に Dockerfile 内で systemd を最新バージョンにアップグレードして、`docker run` を実行する際に特定のオプションを付与すれば CentOS 7 な systemd container を稼働させることができました。参考までに。

https://github.com/docker/for-mac/issues/6073#issuecomment-1061207986

## TL;DR

- cgroup v2 がサポートされている systemd 247 以上を使用すること
- `--privileged --cgroupns=host -v /sys/fs/cgroup:/sys/fs/cgroup:rw` オプションを付与してコンテナを起動すること

## はじめに

開発中に CentOS 7 コンテナ内で systemd を起動したいケースが出てきたので、インターネットで多くの方が紹介している方法 [^1] を試したら、正常に systemd が起動しない事象に直面したので、どのようにしたら systemd を起動できるか調査しました。

## 調査結果

cgroup v2 を使用してコンテナを実行する環境では CentOS 7 の systemd container を動かせないとの報告を見つけました。この問題は systemd のバージョンが古いことに起因しているようです。

https://github.com/geerlingguy/docker-centos7-ansible/issues/12#issuecomment-894458977

自分の環境（Docker Desktop for Mac 4.3.0）で cgroup v2 が使用されているのか不明だったので、`docker info` を実行したところ、Docker Engine は `v20.10.11` で `Cgroup Version: 2` となっていることから cgroup v2 が使用されていることがわかりました。つまり、この時点で CentOS 7 の systemd container を動かせないということになります。

```bash
$ docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc., v0.7.1)
  compose: Docker Compose (Docker Inc., v2.2.1)
  scan: Docker Scan (Docker Inc., 0.9.0)

Server:
 Containers: 11
  Running: 0
  Paused: 0
  Stopped: 11
 Images: 334
 Server Version: 20.10.11
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 2
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
 runc version: v1.0.2-0-g52b36a2
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
  cgroupns
 Kernel Version: 5.10.76-linuxkit
 Operating System: Docker Desktop
 OSType: linux
 Architecture: x86_64
 CPUs: 4
 Total Memory: 5.805GiB
 Name: docker-desktop
 ID: OFQN:IYYA:PWPG:FNJA:ZAW3:USMJ:EZH7:T7KA:R55Z:VGWM:HGIJ:T4LE
 Docker Root Dir: /var/lib/docker
 Debug Mode: true
  File Descriptors: 44
  Goroutines: 46
  System Time: 2021-12-10T09:02:58.092150033Z
  EventsListeners: 3
 HTTP Proxy: http.docker.internal:3128
 HTTPS Proxy: http.docker.internal:3128
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false
```

補足ですが Docker での cgroup v2 サポートは v20.10 から開始されたようです。

https://github.com/docker/docker.github.io/pull/11042

ここまで調べて何気なく Docker Desktop のリリースノートを眺めていたら、以下の記載から、やはり cgroup v2 環境では CentOS 7 の systemd container を動かせないようです。どうにかして動かすことができるのかもしれませんが、今回はそこまで深堀りはしませんでした。

> ### Bug fixes and minor changes
>
> - Docker Desktop now uses cgroupv2. If you need to run `systemd` in a container then:
>   - Ensure your version of `systemd` supports cgroupv2. [It must be at least `systemd` 247](https://github.com/systemd/systemd/issues/19760#issuecomment-851565075). Consider upgrading any `centos:7` images to `centos:8`.
>   - Containers running `systemd` need the following options: `--privileged --cgroupns=host -v /sys/fs/cgroup:/sys/fs/cgroup:rw`.

https://docs.docker.com/desktop/mac/release-notes/#docker-desktop-430

以上です。ニッチな内容ですがどなたかの役に立てたら幸いです。

## 参考資料

- https://blog.tiqwab.com/2021/05/09/systemd-container.html
- https://serverfault.com/questions/1053187/systemd-fails-to-run-in-a-docker-container-when-using-cgroupv2-cgroupns-priva/1054414

[^1]: CentOS 公式の systemd container（ https://github.com/CentOS/CentOS-Dockerfiles/tree/master/systemd/centos7 ）でも採用されている `/sbin/init` をエントリーポイントに設定して `--privileged` オプションでコンテナを起動する方法。