〔備忘録〕 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 を利用する。
【参考にしたサイト】
- https://superuser.com/questions/688733/start-a-systemd-service-inside-chroot
- https://wiki.archlinuxjp.org/index.php/Systemd-nspawn
- https://unix.stackexchange.com/questions/347881/why-does-the-nspawn-of-an-ubuntu-image-fail
- http://manpages.ubuntu.com/manpages/xenial/en/man8/debootstrap.8.html
- http://manpages.ubuntu.com/manpages/xenial/en/man1/systemd-nspawn.1.html
- http://manpages.ubuntu.com/manpages/xenial/en/man1/machinectl.1.html
- http://h-s-maga.blogspot.jp/2016/06/machinectlkali.html
【確認環境】
- OS: Ubuntu 16.04 LTS (xenial) / security updated on 2017-May-26 by apt-get upgrade
- PC: Virtualbox 5.1 仮想マシン
【構築手順】
- (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 にする。
ホスト側で、以下を実行する。
更に、/etc/nsswitch.conf の hosts: セクションに mymachines を追加します。
host# systemctl enable --now systemd-networkd systemd-resolved
host# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
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 testConnected 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 でも行えるようです。しかし、その違い・メリットデメリットが分からないので、今後調査していく必要があります。