〔備忘録〕 Ubuntu 16.04LTS (xenial) 上での chroot 環境の構築方法

【動機】

Ubuntu 16.04LTS (xenial) 上で、chroot環境下で動作する DNS Server (BIND9) を構築しようとしたら chroot 環境が作れなかったので、調査結果&作成手順をメモ。

Ubuntu 16.04LTS では systemd が採用されており、以下のように bind9.service ファイルで起動オプションに -t {chroot directory} を追加しただけでは、動作しなかった。


[Unit]
Description=BIND Domain Name Server
Documentation=man:named(8)
After=network.target

[Service]
ExecStart=/usr/sbin/named -f -u bind -t /chroot/named
ExecReload=/usr/sbin/rndc reload
ExecStop=/usr/sbin/rndc stop

[Install]
WantedBy=multi-user.target



【方法概要】

systemd 環境下で chroot 環境を構築するための systemd-nspawn を利用する。



【参考にしたサイト】


【確認環境】


【構築手順】

  • (1) Host マシン(上記の Virtualbox 仮想マシン上)で、以下のパッケージをインストールする。


$ sudo apt-get install systemd-container debootstrap ubuntu-keyring

  • (2) コンテナを作成する(イメージ名はtest)。


$ cd /var/lib/machine
$ sudo debootstrap --arch=amd64 --variant=minbase \
--include=dbus,netbase,net-tools,ifupdown,vim,apt,sudo \
xenial test http://jp.archive.ubuntu.com/ubuntu

  • (3) chroot 環境側 の初期設定(ユーザの追加、追加ユーザのsudo権限付与、rootユーザのロック、コンソールログイン用のttyの設定)を行う。


host# systemd-nspawn -D test
test# adduser testuser
test# sed -E '/^sudo/s/:$/:testuser/g' /etc/group > /tmp/group ; mv /tmp/group /etc/group
test# passwd -l root
test# echo 'pts/0' >> /etc/securetty
test# exit

  • (4) chroot 環境側 Network IF を host 側の IF にする。

ホスト側で、以下を実行する。


host# systemctl enable --now systemd-networkd systemd-resolved
host# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
更に、/etc/nsswitch.conf の hosts: セクションに mymachines を追加します。

hosts: files mymachines dns myhostname

最後に、/lib/systemd/system/systemd-nspawn@.service ファイル内の起動コマンドの設定から、"--network-veth" オプションを削除し、コンテナ側の Network IF をホストの NIF と同じにする。

修正前:


[Service]
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot \
--link-journal=try-guest --network-veth \
--settings=override --machine=%I

修正後:


[Service]
ExecStart=/usr/bin/systemd-nspawn --quiet --keep-unit --boot \
--link-journal=try-guest \
--settings=override --machine=%I



chroot環境使用手順】

まず、作成したコンテナを起動します。


host# machinectl start test

次に、コンテナにログインします。


host# machinectl login test

Connected to machine test. Press ^] three times within 1s to exit session.

Ubuntu 16.04 LTS test pts/0

bindtest login: testuser
Password:
Last login: Fri May 26 15:04:31 UTC 2017 on pts/0
Welcome to Ubuntu 16.04 LTS (GNU/Linux 4.4.0-62-generic x86_64)

* Documentation: https://help.ubuntu.com/
testuser@test:~$

※ これ以降はコンテナ内での作業になりますので、私の目的である「bind9 のインストール」となりますが、この記事の範疇外になるので割愛します。


コンテナからログオフするには、1秒以内に Ctrl-] を3回押します。

コンテナを shutdown するのは、


host# machinectl poweroff test
です。




【所感】

感覚的には、今までの chroot 環境というより、 FreeBSD の jail 環境に近いように思えます。

今回は、『systemd で動作させようとした bind9 が chroot 環境で動かせない』というのが発端で、調べていったら systemd-nspawn にたどり着いたのですが、
同様の仕組みは docker や LXC, LXD でも行えるようです。しかし、その違い・メリットデメリットが分からないので、今後調査していく必要があります。