Ubuntu Weekly Recipe

第659回systemd-nspawn+pbuliderでパッケージのビルド環境を整える

今回はsystemd-nspawnとpbuilderを組み合わせ、パッケージをビルドする環境を整えます。

筆者流ビルド環境の整え方

FlatpakやSnapパッケージの普及により自分でパッケージをビルドして最新版のアプリケーションを使用するという機会は確実に減っています。どうしてもパッケージをビルドする必要ができた時も、DockerだLXCだmultipassだクラウドだと、環境の作り方はさまざまです。いずれにせよ共通するのは、手元の環境を汚さないということです。

ビルド環境は維持するのか逐次作成するのかも悩みどころですが、あまり頻繁にパッケージのビルドを行わない場合はどこかのクラウドサービスを借りるのがいいでしょう。ビルドに必要なハードウェアリソースは、たまにしか使用しないのであれば外部サービスを使用したほうが安上がりです。もちろんビルドするパッケージにもよるのですが。

ローカルでビルドする場合はいかようにもすればいいのですが、ハードウェアリソースは自前で確保しなければなりません。特にビルド時間に影響を及ぼすのはそれなりの性能のCPU、メモリー、ストレージです。ビルドはどうしてもトライ&エラーの繰り返しとなることが多く、かといって1日は等しく24時間しかないため、ハードウェアリソースが潤沢な場合はそれだけトライ&エラーの回数を増やすことができるというわけです。

ソースパッケージをビルドするだけであれば、ローカルに必要なパッケージをインストールしてビルドすればいいでしょうが、PPAにアップロードする場合は、クリーンなビルド環境を用意する必要があります。厳密にいえば依存するパッケージが100%把握できている場合は不要といえばそうなのですが、ちょっと現実的とは思えません[1]⁠。ただし毎回クリーンなビルド環境を使用するとオーバーヘッドが大きくなるため、併用できると便利でしょう。

というわけで、筆者は可能な限りクリーンなビルドを行いつつ、場合によってはローカルでビルドしています。⁠ローカルでビルド」とは、具体的にはdpkg-buildpackageコマンドを実行してパッケージをビルドすることを指しています。クリーンなビルド環境はpbuilderを使用しています。これらを同居するため、第491回で紹介したsystemd-npawnを使用してコンテナを作成します。

pbuilderで事前にビルドしたパッケージを依存関係で使用している、なんてこともよくあるわけですが、pbuilderをセットアップしただけでは自身でビルドしたパッケージを使用してビルドすることはできず、この問題の解決も重要です。

長くなりましたが、今回はsystemd-nspawnでコンテナを作成し、pbuilderでビルド環境を構築する方法を紹介します。

例としてUbuntu 20.04 LTS上で開発版の21.04のビルド環境を構築してみますが、18.04 LTS以降であればおおむねどの組み合わせでも対応できると思います。

必要なパッケージ

必要なパッケージをインストールします。次のコマンドを実行してください。

$ sudo apt install systemd-container debootstrap

コンテナを作成する

systemd-nspawnの使い方は第491回に準じるのですが、今は少し簡単になっているので改めて紹介します。

まずはコンテナーを作成するフォルダーを作成し、debootstrapコマンドを実行します。作成するのは/var/nspawn/hirsuteとします。⁠hirsute⁠はUbuntu 21.04開発版のコードネームです。次のコマンドを実行してください。

$ sudo mkdir -p /var/nspawn/hirsute
$ sudo debootstrap hirsute /var/nspawn/hirsute

“Base system installed successfully.⁠と表示されると完了です。開発版のdebootstrapコマンドは実行に失敗するタイミングもあるため、必ずこのメッセージが表示されることを確認してください。リリース後であれば、おおむね問題となることはないでしょう。

作成したコンテナーにはユーザーがないため、作成します。

$ sudo systemd-nspawn -D /var/nspawn/hirsute

コンテナーにログインできたので、ユーザーを作成します。作成するユーザーは⁠ikuya⁠としますので、適宜読み替えてください。

# useradd ikuya -G sudo -m
# passwd ikuya

同じパスワードを2回入力し、一致した場合はパスワードの設定ができて準備完了です。ここまでできたら、一度ログアウトしてください。

# exit

いよいよコンテナを起動します。次のコマンドを実行してください。

$ sudo systemd-nspawn -b -D /var/nspawn/hirsute

以後はログインしたコンテナ内での作業となります。

コンテナの設定

コンテナにログインしたら、まずはログインシェルを変更します。/bin/shは使いにくいでしょう。次のコマンドを実行してください。

$ sudo chsh -s /bin/bash ikuya

一度ログアウトして再ログインすると、見慣れたbashが起動しているでしょう。

リポジトリの情報を変更します。/etc/apt/sources.listを次のように変更してください。

deb http://jp.archive.ubuntu.com/ubuntu hirsute main universe
deb-src http://jp.archive.ubuntu.com/ubuntu hirsute main universe
deb http://jp.archive.ubuntu.com/ubuntu/ hirsute-updates main universe multiverse
deb-src http://jp.archive.ubuntu.com/ubuntu/ hirsute-updates main universe multiverse

次のコマンドを実行し、リポジトリの情報をアップデートしてください。

$ sudo apt update

エラーが出ていないことを確認してください。

最低限エディターを変更し、bash-completionをインストールすることも必須でしょう。エディターは今回はvimとしますが、お好きなものにしてください。次のコマンドを実行してください。

$ sudo apt install vim bash-completion

一度ログアウトして再ログインするとbash-completionが有効になります。

コンテナであることをわかりやすくするため、ホスト名も変更したほうがいいでしょう。今回では例として⁠nspawn-hirsute⁠に変更します。次のコマンドを実行してください。

$ sudo hostnamectl set-hostname nspawn-hirsute

/etc/hostnameの設定はしてくれますが、/etc/hostsの設定はしてくれないので、⁠127.0.0.1 (ホスト名)⁠を追加してください(IPアドレスとホスト名の間に入っているのはタブです⁠⁠。

やはり一度ログアウトして再ログインするとホスト名が変わっています。

コンテナの設定はキリがないのでこのぐらいにしておきます。

pbuilder環境を構築する

pbuilderももちろんコンテナー内に作成します。まずは必要なパッケージをインストールします。次のコマンドを実行してください。

$ sudo apt install ubuntu-dev-tools pbuilder --no-install-recommends

pbuilder内部で使用するコンテナ(chrootイメージをtarで固めたもの)を作成します。次のコマンドを実行してください。

$ pbuilder-dist hirsute create

debootstrapと同じく、作成までしばらく時間がかかります。

"pbuilder/(コードネーム)_result/D05deps⁠を次の内容で作成します。今回の例ではもちろん⁠pbuilder/hirsute_result/D05deps"です。ただしユーザー名は適宜変更してください。

#!/bin/bash
(cd /home/ikuya/pbuilder/hirsute_result/; apt-ftparchive packages . > Packages && gzip -c Packages >Packages.gz)
apt update

パッケージが作成されたフォルダーをリポジトリとするために必要な情報を作成し、リポジトリ情報を更新しています。シェルスクリプトにもなっているため、次のコマンドを実行して実行権限を付与してください。

$ chmod 755 pbuilder/hirsute_result/D05deps

pbuilderの情報は~/.pbuilderに設定します。次の内容にしてください。ただしユーザー名は適宜変更してください。

$ cat ~/.pbuilderrc
# this is your configuration file for pbuilder.
# the file in /usr/share/pbuilder/pbuilderrc is the default template.
# /etc/pbuilderrc is the one meant for overwriting defaults in
# the default template
#
# read pbuilderrc.5 document for notes on specific options.
MIRRORSITE=http://jp.archive.ubuntu.com/ubuntu
UBUNTUTOOLS_UBUNTU_MIRROR=http://jp.archive.ubuntu.com/ubuntu/
APTCACHEHARDLINK=no
COMPONENTS="main restricted multiverse universe"
#for internal repo
OTHERMIRROR="deb [trusted=yes] file:///home/ikuya/pbuilder/hirsute_result ./"
BINDMOUNTS="/home/ikuya/pbuilder/hirsute_result/"
HOOKDIR="/home/ikuya/pbuilder/hirsute_result/"
EXTRAPACKAGES="apt-utils"

リポジトリとして機能するようにしておきます。次のコマンドを実行してください。

$ cd pbuilder/hirsute_result
$ apt-ftparchive packages . > Packages && gzip -c Packages >Packages.gz
$ cd -

pbuilderの情報を更新します。次のコマンドを実行してください。

$ pbuilder-dist hirsute update --override-config
$ pbuilder-dist hirsute update --override-config --othermirror "deb [trusted=yes] file:///home/ikuya/pbuilder/hirsute_result /|deb http://jp.archive.ubuntu.com/ubuntu/ hirsute-updates main universe restricted"  --mirror http://jp.archive.ubuntu.com/ubuntu/ --components "main restricted universe multiverse"

奇妙な感じですが、必ずこの順番で実行する必要があります。これでひととおり完了です。

試しにMozcをビルドしてみましょう。次のコマンドを実行してください。

$ pull-lp-source mozc hirsute
$ pbuilder-dist hirsute build mozc_(バージョン).dsc

1行目のコマンドでUbuntu 21.04開発版のリポジトリからMozcのソースパッケージを取得しています。2行目のコマンドでMozcをビルドしています、⁠.dsc⁠が付くファイルを引数の最後につけます。

dpkg-buildpackageコマンドでもパッケージをビルドしてみましょう。次のコマンドを実行してください。

$ cd mozc_(バージョン)
$ sudo apt build-dep mozc
$ dpkg-buildpackage -r -uc -b

コンテナを終了する

コンテナを終了する場合は次のコマンドを実行してください。

$ sudo poweroff

ホストで実行しないように注意してください。ホスト名が変更されているため、誤った操作はしないはずではあります。

おすすめ記事

記事・ニュース一覧