BuildKit上でsbuildを使いDebianパッケージをビルドする
目次
Debianパッケージのお手軽なビルド環境として、BuildKit上でsbuildの環境を構築しビルド実行する。これにより、環境構築・ビルド方法をDockerfile
にまとめることができ、Docker Bakeを使って複数のターゲットを同時にビルドすることができる。
背景・目的
Debianパッケージのビルドツールとして、pbuilder
やsbuild
がある。どちらも環境構築が必要であるが、設定ファイルやchroot環境のカスタマイズなど、人によって若干異なる環境が出来上がってしまうことがある。環境構築部分から実際のビルド部分までを一つのDockerfile
にまとめることによって、環境構築手順を明示することができる。
なお、builddと同じ環境を作ることを目的としているわけではない。
レポジトリはGitHubに置いている。
動作の流れ
- DockerベースイメージはUbuntu 24.04とする
sbuild
のunshare
モードではroot権限不要のため、ビルド用ユーザーを作成する- 必要なものをインストールする
unshare
モードでsbuild
を実行するため、sbuild
はnoble-backportsのものをインストールする
mmdebstrap
でターゲットのディストリビューション・アーキテクチャの環境を構築する- 丁度buildd用のバリアントがあるのでそれを使う
- 古いディストリにビルドする場合、新しい
sbuild
では対応できない部分があるため、回避策を入れる- Ubuntu 14.04
/var/lib/dpkg/available
をtouch
してapt
が動作するようにする/etc/passwd
や/etc/group
を修正しapt
が動作するようにするdpkg-genchanges
に--build=source
という長いオプションがないため-S
に置き換え
- Ubuntu 16.04
pam-auth-update
によってapt
(確か)が動作するようにするdpkg-genchanges
に--build=source
という長いオプションがないため-S
に置き換え
- Ubuntu 14.04
sbuild
の設定ファイル~/.config/sbuild/config.pl
を作る- Debian Wikiに書いてあるのとだいたい同じだが、一部異なる
lintian
、autopkgtest
、piuparts
を無効化- インストールすれば多分動くと思うが…
- ビルド先ディレクトリを指定
- ビルド前にソースパッケージのcleanをしない
pbuilder
もそうだが、cleanにBuild-Dependsのパッケージが必要なことがあり、unshare前にcleanをする場合イメージ内にBuild-Dependsのパッケージを入れなければならない- どちらにしてもunshare後にもう一度cleanをするため、ビルド前のcleanは無効にする
- Debian Wikiに書いてあるのとだいたい同じだが、一部異なる
- ソースをコピーする
sbuild
を実行する/dev/console
がないと動かないことがあるため、ここで作成- tmpfsマウントで高速化を図る
sbuild
の結果ビルドディレクトリに何も出力されなかった場合、代わりにsbuild
の標準出力を配置scratch
イメージに成果物を置く- これによってコンテナ実行をすることがなくなり、BuildKitだけで動作するようになる
- ローカルフォルダーに成果物だけ入ったイメージを出力する
Docker化の利点
- 環境構築や設定ファイル(やろうと思えば)などを1個のDockerfileにすべて詰め込めるため、可搬性が高い
- ワークアラウンドもDockerfileに明記されるため、「PC新調したらビルドできなくなったんだけど今までどうやってたんだっけ?」というやり直しがなくなる
- ビルドキャッシュが効く環境であれば、環境構築部分をキャッシュすることができる
- Dockerの特性として、比較的再現性が高い
- Rootlessイメージビルドの手法を組み合わせれば、Rootlessでビルドできる(はず)
Docker Bakeによるマルチターゲットビルド
Dockerイメージを作ってそれを起動してビルドするのではなく、scratch
イメージを利用して成果物のみ入ったイメージを構築してそれをローカルファイルとして出力する方法にはいくつかメリットがあるが、その一つがDocker Bakeを使って同時に複数のターゲットをビルドできることである。
docker-bake.hcl
でビルドターゲットをマトリックスで指定でき、BuildKitのオプションも書いておくことができる。例えば、出力先は./build/${dist}-${arch}
にするような記述をしておくことや、実行にはsecurity.insecure
の許可が必要なことが記載できる。
また、Docker Bakeはターゲットによらず共通の部分はまとめて1回だけ命令処理するようなので、apt install
のような共通部分を複数回実行しなくて済むこともメリットと言えるかもしれない。