最近LXC - Linux Containersで開発環境を構築したので、その作業の中からコンテナのカスタマイズについて書きます1。
LXCではlxc-createコマンドでテンプレートを指定してコンテナを作成します。例えば、Fedora19のコンテナを作成するコマンドは以下の通りです。
$ sudo lxc-create -t fedora -n fedora19 -- --release 19
これで作成されるのはミニマムな環境なので、色々とパッケージを追加したりユーザを追加したり設定をしたりして使うことになります。 Chef などのプロビジョニングツールを利用して初期設定をすることもできますが、開発環境にそれらのツールを導入したくない場合もあります。
ここではFedora向けのテンプレートを改造して、パッケージを追加する方法を簡単に紹介します。
まず、実装を確認します。/usr/share/lxc/templates/lxc-fedora
の内容を確認すると、ただのシェルスクリプトであることがわかります。
このファイルの最後の方を確認すると以下のように、前の方で定義した関数を順番に実行しているだけです。全部引用すると長くなるので重要な部分のみを引用しています。
trap revert SIGHUP SIGINT SIGTERM
copy_configuration
install_fedora
configure_fedora
type /bin/systemd >/dev/null 2>&1
if [ $? -ne 0 ]; then
configure_fedora_init
else
configure_fedora_systemd
fi
echo "container rootfs and config created"
これを見るとcopy_configuration
で設定をコピーしてinstall_fedora
でFedoraをインストールした後configure_fedora
でFedoraの設定をしています。
最後にsystemdの有無で、設定を変えています。
順番に見ていくとcopy_configuration
はコンテナの設定ファイルを所定のパスに作成しているだけなので、今回は変更する必要がありません。
install_fedora
の中では、キャッシュがあったらそれを更新(update_fedora
)してから、コピー(copy_fedora
)しています。
キャッシュがなればダウンロード(download_fedora
)してから、コピー(copy_fedora
)しています。
なので、download_fedora
の中身を見れば、どうやってカスタマイズすれば良いのかわかりそうです。
download_fedora
ではyumの--installroot
オプションを使ってパッケージのインストール先を変更しつつchroot環境を構築し、完成したディレクトリツリーを所定のパスに移動しています。
またFedoraのバージョンでfedora-releaseというパッケージの命名規則が変わっていますが、うまくインストールできるようにしています。
重要な部分を引用すると以下の通りです。
download_fedora()
{
# download a mini fedora into a cache
echo "Downloading fedora minimal ..."
YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
PKG_LIST="yum initscripts passwd rsyslog vim-minimal dhclient chkconfig rootfiles policycoreutils fedora-release"
MIRRORLIST_URL="http://mirrors.fedoraproject.org/mirrorlist?repo=fedora-$release&arch=$arch"
# fedora-release-*.rpm をダウンロードしている部分は省略
mkdir -p $INSTALL_ROOT/var/lib/rpm
rpm --root $INSTALL_ROOT --initdb
rpm --root $INSTALL_ROOT -ivh $INSTALL_ROOT/fedora-release-$release.noarch.rpm
$YUM install $PKG_LIST
mv "$INSTALL_ROOT" "$cache/rootfs"
echo "Download complete."
return 0
}
単純に考えるとPKG_LIST
に欲しいパッケージを追加すればよさそうです。しかし、それだとパッケージリストを変更して試すために毎回テンプレートを修正しなければなりません。
それは面倒なので、追加のパッケージリストは別ファイルにしてテンプレートのオプションで指定できるようにしてみます。
元にしたテンプレートをコピーして/usr/share/lxc/templates/
以下に lxc-で始まる名前で置けばテンプレートとして使うことができます。
例えばlxc-fedora-customという名前でファイルを作成するとlxc-createで指定するテンプレート名はfedora-customになります。
ここではFedora向けのテンプレートをコピーしたものに機能を追加します。
差分はこうなります。
--- lxc-fedora 2014-04-28 11:38:41.960333132 +0900
+++ lxc-fedora-custom 2014-04-28 12:18:29.650862732 +0900
@@ -178,6 +178,12 @@
return 1
fi
+ if [ ! -z "$package_list" ]; then
+ echo "Install extra packages"
+ $YUM groupinstall $(grep -E "^@" "$package_list" | sed -e "s,^@,,")
+ $YUM install $(grep -v -E "^(#|@)" "$package_list")
+ fi
+
mv "$INSTALL_ROOT" "$cache/rootfs"
echo "Download complete."
@@ -322,12 +328,13 @@
-c,--clean clean the cache
-R,--release Fedora release for the new container. if the host is Fedora, then it will defaultto the host's release.
-A,--arch NOT USED YET. Define what arch the container will be [i686,x86_64]
+ --package-list Path to package list file
-h,--help print this help
EOF
return 0
}
-options=$(getopt -o hp:n:cR: -l help,path:,name:,clean,release: -- "$@")
+options=$(getopt -o hp:n:cR: -l help,path:,name:,clean,release:,package-list: -- "$@")
if [ $? -ne 0 ]; then
usage $(basename $0)
exit 1
@@ -342,6 +349,7 @@
-n|--name) name=$2; shift 2;;
-c|--clean) clean=$2; shift 2;;
-R|--release) release=$2; shift 2;;
+ --package-list) package_list=$2; shift 2;;
--) shift 1; break ;;
*) break ;;
esac
1行に1つパッケージ名を書いたテキストファイルを用意して --package-list オプションに指定すれば追加のパッケージをインストールしたコンテナを簡単に作ることができます。
このパッチをあてたテンプレートは以下のように利用します。
$ sudo lxc-create -t fedora-custom -n my-fedora19 -- --release 19 --package-list packages.txt
追加のパッケージをインストールする以外にも様々なカスタマイズが考えられます。
- Ubuntuのテンプレートのようにホスト側のユーザをコンテナ側にも作成して、そのユーザのホームディレクトリをバインドマウントする
- アーキテクチャを指定できるようにする
- mirror URLを指定できるようにする
- 別のディストリビューションのテンプレートを作成する
まとめ
LXCのテンプレートをカスタマイズして、初期導入パッケージをカスタマイズする方法を紹介しました。
-
LXCのバージョンは0.9系を想定していますが、0.8でも1.0でも基本的には変わりません。 ↩