chroot(8)を使ってホストから分離された環境を作る


コンテナ型の仮想化技術を利用したいとき、GNU/LinuxではDockerやLXC、FreeBSDではJailを利用することになります。一方NetBSDでコンテナを動かしたいのであればchroot(8)をそのまま使わざるをえません。

DockerではDockerfileをビルドしたコンテナイメージが様々なFLOSSプロジェクトから公式に提供されており、docker pullでダウンロードしてそのまま動かせます。Jailはiocageに代表される便利な管理マネージャが存在します。これらのような便利なツールを使っているとchroot(8)をそのまま使うのはとても敷居が高いように思えます。しかし、NetBSDのBase Systemの展開とpkg_add(1)-Pオプション、mount_null(8)の使い方を把握しておけば、思い通りにchroot(8)コンテナイメージを構築できます。

  1. NetBSD Base System
  2. コンテナにパッケージをインストールする
  3. ホスト側のディレクトリをコンテナにマウントする

NetBSD Base System

ホスト環境と同じバージョンのBase SystemのセットをFTPサーバからダウンロードします。最小のコンテナを構築するのであれば、base.tgzとetc.tgzの2つをダウンロードします。

$ ftp ftp://ftp.iij.ad.jp/pub/NetBSD/NetBSD-8.0/amd64/binary/sets/
...
ftp> mget base.tgz etc.tgz

コンテナのルートディレクトリを作成します。ここでは$HOME/containers/netbsd_minimalディレクトリをコンテナのルートとします。先ほどダウンロードしたtarballをこのディレクトリに展開してください。

$ mkdir -p $HOME/containers/netbsd_minimal
$ tar zxf base.tgz -C $HOME/containers/netbsd_minimal
$ tar zxf etc.tgz -C $HOME/containers/netbsd_minimal

MAKEDEV(8)スクリプトを実行し、特殊ファイルを作成します。

$ cd $HOME/containers/netbsd_minimal/dev
# sh MAKEDEV all

名前解決するためにホスト側の/etc/resolve.confをコンテナへコピーします。

$ cp /etc/resolve.conf $HOME/containers/netbsd_minimal/etc

これで最小のNetBSDコンテナを構築できました。次のようにchroot(8)コマンドを実行して、コンテナの中に入ります。コンテナから抜けるにはexitします。

$ cd $HOME/containers
# chroot netbsd_minimal sh

コンテナにパッケージをインストールする

ホスト側からpkg_add(1)し、コンテナイメージにパッケージをインストールします。たとえばshells/zshパッケージをコンテナにインストールしてみます。

# cp -pr netbsd_minimal netbsd_custom
# pkg_add -P ./netbsd_custom /usr/pkgsrc/packages/All/zsh-5.7.1nb1.tgz

この例では、netbsd_minimalイメージをnetbsd_customイメージとして複製し、shells/zshパッケージをインストールしました。pkg_add(1)-Pオプションにコンテナのルートディレクトリを指定すると、そのディレクトリ直下にあるusr/pkg/ディレクトリにバイナリがインストールされ、var/db/pkgデータベースにパッケージが登録されます。ホスト側の環境を汚しません。

ホスト側のディレクトリをコンテナにマウントする

chroot(8)環境下でpkgsrc(7)のパッケージをビルドするとき、ホスト側の/usr/pkgsrcディレクトリを共有すると、コンテナ側で作成したパッケージにホスト側の/usr/pkgsrc/packages/Allからアクセスできるため便利です。逆にコンテナ側からホスト側の/usr/pkgsrc/packages/Allにアクセスできると、既にビルドしてあるパッケージを再ビルドせず使いまわせます。

ホスト側からコンテナのルートへシンボリックリンクを貼っても、コンテナ側からはアクセスできません。そのため、ホスト側にある特定のディレクトリをコンテナと共有するにはmount_null(8)でホスト側のディレクトリをコンテナへマウントします。

# mkdir netbsd_custom/usr/pkgsrc
# mount_null /usr/pkgsrc netbsd_custom/usr/pkgsrc

なお、pkgsrc(7)のパッケージビルドにはBase Systemのcomp.tgzをコンテナに展開する必要があります。X11系のパッケージビルドにはxcomp.tgzも必要です。