前回記事でlimaのセットアップをしたので、これを利用してlimaインスタンス上でCentOS7コンテナのsystemdを利用することにした。
なんでlima+dockerでやるの?
自分は今までDocker Desktopを使っており、CentOS7コンテナのsystemdは普通に利用してきた(--privileged
つけたり/sbin/init
でdocker runしたりするあれ)。
しかし、 Docker Desktop 4.3.0以降はこれができなくなった。
Docker Desktop for Mac release notes | Docker Documentation
- Docker Desktop now uses cgroupv2. If you need to run systemd in a container then:
Docker Desktopでcgroup v2
を使うようにした関係で、cgroup v1
を使っているとsystemdを実行することができなくなっている。
CentOS7は cgroup v1
なのでこれに引っかかって動かない。
上記でも「cgroup v2
をサポートしているsystemd 247以上を使う必要あり。centos:7はcentos:8などcgroup v2
が使えるOSイメージへ移行して--privileged --cgroupns=host -v /sys/fs/cgroup:/sys/fs/cgroup:rw
をつけてコンテナを起動すること。」と書かれている。
自分の場合、CentOS7イメージでsystemdを起動できるコンテナを使う場面がまだ必要で、Docker Desktop以外で利用する手段がほしいところ。
というわけで前回記事でlimaを使えるようにしたことを活かして、cgroup v1
が使えるlimaインスタンスを構築してCentOS7コンテナのsystemdを使えるようにした。
先にMacOS環境にdocker clientをインストールしておく
Docker Desktopはアンインストールして、docker clientをインストールしておく。
ref : Install Docker Engine from binaries | Docker Documentation
簡単にlimaインスタンスを構築できるyamlファイルを用意した
やったことをいろいろ説明する前に成果物を見せちゃおう。
limactl start
でインスタンスを作成するときにいい感じにprovisionしてくれるyamlを作成した。
私のリポジトリで公開しているのでどうぞ。
yamlファイルを手元にもってきてlimactl start
のときに指定するだけでインスタンスが立ち上がり、dockerデーモンのセットアップもしてくれる。
$ limactl start /path/to/docker-vm.yaml
あとは環境変数DOCKER_HOST
を設定してcentos7のコンテナをdocker runするだけ。
これでsystemdを利用できる。
$ export DOCKER_HOST='tcp://127.0.0.1:2375' $ docker run -itd --privileged --name centos7 centos:7 /sbin/init cadb0f349dc55d7d398b51398f3a411d8e94fcadf8b4499b9d2fb4050d2602d1 $ docker exec -it centos7 systemctl status ● cadb0f349dc5 State: starting Jobs: 6 queued Failed: 0 units Since: Tue 2022-01-18 02:56:21 UTC; 10s ago CGroup: /docker/cadb0f349dc55d7d398b51398f3a411d8e94fcadf8b4499b9d2fb4050d260 2d1 ├─1 /sbin/init └─system.slice ├─systemd-udevd.service │ └─32 /usr/lib/systemd/systemd-udevd ├─systemd-journald.service │ └─21 /usr/lib/systemd/systemd-journald ├─dbus.service │ └─60 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nop idfile --systemd-activation ├─system-getty.slice │ └─getty@tty1.service │ └─69 (agetty) └─systemd-logind.service └─65 /usr/lib/systemd/systemd-logind
作成したyamlファイルのポイント
limaではlimactl start
するだけでインスタンスが起動してくれるが、デフォルトの設定をそのまま使っても求める環境は構築できない。
以下ポイントを2点ほどまとめた。
ポイント1:limaインスタンスのOSはRocky Linux 8.5を採用
デフォルトで起動するインスタンスはUbuntu 21.10だが、cgroup v2
が使われているので今回のケースだとNG。
<user>@lima-default:~$ grep PRETTY_NAME /etc/os-release PRETTY_NAME="Ubuntu 21.10" <user>@lima-default:~$ <user>@lima-default:~$ journalctl --version systemd 248 (248.3-1ubuntu8.2) +PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SECCOMP +GCRYPT +GNUTLS -OPENSSL +ACL +BLKID +CURL +ELFUTILS -FIDO2 +IDN2 -IDN +IPTC +KMOD +LIBCRYPTSETUP -LIBFDISK +PCRE2 -PWQUALITY -P11KIT -QRENCODE +BZIP2 +LZ4 +XZ +ZLIB +ZSTD -XKBCOMMON +UTMP +SYSVINIT default-hierarchy=unified <user>@lima-default:~$ <user>@lima-default:~$ <user>@lima-default:~$ mount | grep cgroup cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot) <user>@lima-default:~$
docker clientのinfoからも確認できる。
$ docker info | grep -E "Cgroup Driver:|Cgroup Version:|Operating System:" Cgroup Driver: systemd Cgroup Version: 2 Operating System: Ubuntu 21.10
Rocky Linux 8.5はcgroup v1
なのでOK。
limaのリポジトリにRocky Linuxのサンプルyamlが公開されていたのでこれを利用することにした。
cgroup v1
が使われているOSならRocky Linuxじゃなくてもいけるはず。
[<user>@lima-docker-vm ~]$ cat /etc/redhat-release Rocky Linux release 8.5 (Green Obsidian) [<user>@lima-docker-vm ~]$ [<user>@lima-docker-vm ~]$ journalctl --version systemd 239 (239-51.el8) +PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=legacy [<user>@lima-docker-vm ~]$ [<user>@lima-docker-vm ~]$ [root@base000 current]# mount | grep cgroup tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,seclabel,mode=755) cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,seclabel,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd) ... [<user>@lima-docker-vm ~]$
docker clientのinfoからも確認できる。
$ docker info | grep -E "Cgroup Driver:|Cgroup Version:|Operating System:" Cgroup Driver: cgroupfs Cgroup Version: 1 Operating System: Rocky Linux 8.5 (Green Obsidian)
上記を踏まえてRocky Linux 8.5を採用した。 yamlの該当部分はこんなかんじ。 まずはローカルにOSイメージが無いかを探して、なければ指定されたURLからOSイメージをダウンロードするようになっている。
images: # Try to use a local image first. - location: "~/Downloads/Rocky-8-GenericCloud-8.5-20211114.2.x86_64.qcow2" arch: "x86_64" - location: "~/Downloads/Rocky-8-GenericCloud-8.5.20211114.1.aarch64.qcow2" arch: "aarch64" # Download the file from the internet when the local file is missing. # Hint: run `limactl prune` to invalidate the "current" cache - location: "https://dl.rockylinux.org/pub/rocky/8.5/images/Rocky-8-GenericCloud-8.5-20211114.2.x86_64.qcow2" arch: "x86_64" digest: "sha256:c23f58f26f73fb9ae92bfb4cf881993c23fdce1bbcfd2881a5831f90373ce0c8" - location: "https://dl.rockylinux.org/pub/rocky/8.5/images/Rocky-8-GenericCloud-8.5.20211114.1.aarch64.qcow2" arch: "aarch64" digest: "sha256:f13cfa7b5e449cc165181a1efbea5b1cdce73ef6a5d6bb24c22b50f67f1f8fe2"
ポイント2:provisionを活用する
インスタンスただ作成するだけではMacOSからlimaインスタンス上のdockerデーモンは利用できない。 というかデフォルトだとlimaインスタンスにdockerは入ってない。 さらにdockerのデーモンはlimaで構築したインスタンス上で動いているので、ただインストールするだけではMacOS側のdocker clientを実行してもエラーがでる。 docker clientからlima上のdockerデーモンを利用できるように更に設定を追加する必要がある。
ref : https://docs.docker.jp/config/daemon/daemon.html
インスタンスを構築した後にいちいち設定するのは面倒なのでprovisionを利用した。
provision: # `system` is executed with the root privilege - mode: system script: | #!/bin/bash yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io mkdir -p /etc/systemd/system/docker.service.d/ cat <<EOF > /etc/systemd/system/docker.service.d/docker.conf [Service] ExecStart= ExecStart=/usr/bin/dockerd -H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock EOF systemctl daemon-reload systemctl start docker