BuildKit上でsbuildを使いDebianパッケージをビルドする

目次

Debianパッケージのお手軽なビルド環境として、BuildKit上でsbuildの環境を構築しビルド実行する。これにより、環境構築・ビルド方法をDockerfileにまとめることができ、Docker Bakeを使って複数のターゲットを同時にビルドすることができる。

背景・目的

Debianパッケージのビルドツールとして、pbuildersbuildがある。どちらも環境構築が必要であるが、設定ファイルやchroot環境のカスタマイズなど、人によって若干異なる環境が出来上がってしまうことがある。環境構築部分から実際のビルド部分までを一つのDockerfileにまとめることによって、環境構築手順を明示することができる。

なお、builddと同じ環境を作ることを目的としているわけではない。

レポジトリはGitHubに置いている。

動作の流れ

  1. DockerベースイメージはUbuntu 24.04とする
  2. sbuildunshareモードではroot権限不要のため、ビルド用ユーザーを作成する
  3. 必要なものをインストールする
    • unshareモードでsbuildを実行するため、sbuildはnoble-backportsのものをインストールする
  4. mmdebstrapでターゲットのディストリビューション・アーキテクチャの環境を構築する
    • 丁度buildd用のバリアントがあるのでそれを使う
    • 古いディストリにビルドする場合、新しいsbuildでは対応できない部分があるため、回避策を入れる
      • Ubuntu 14.04
        • /var/lib/dpkg/availabletouchしてaptが動作するようにする
        • /etc/passwd/etc/groupを修正しaptが動作するようにする
        • dpkg-genchanges--build=sourceという長いオプションがないため-Sに置き換え
      • Ubuntu 16.04
        • pam-auth-updateによってapt(確か)が動作するようにする
        • dpkg-genchanges--build=sourceという長いオプションがないため-Sに置き換え
  5. sbuildの設定ファイル~/.config/sbuild/config.plを作る
    • Debian Wikiに書いてあるのとだいたい同じだが、一部異なる
      • lintianautopkgtestpiupartsを無効化
        • インストールすれば多分動くと思うが…
      • ビルド先ディレクトリを指定
      • ビルド前にソースパッケージのcleanをしない
        • pbuilderもそうだが、cleanにBuild-Dependsのパッケージが必要なことがあり、unshare前にcleanをする場合イメージ内にBuild-Dependsのパッケージを入れなければならない
        • どちらにしてもunshare後にもう一度cleanをするため、ビルド前のcleanは無効にする
  6. ソースをコピーする
  7. sbuildを実行する
    • /dev/consoleがないと動かないことがあるため、ここで作成
    • tmpfsマウントで高速化を図る
  8. sbuildの結果ビルドディレクトリに何も出力されなかった場合、代わりにsbuildの標準出力を配置
  9. scratchイメージに成果物を置く
    • これによってコンテナ実行をすることがなくなり、BuildKitだけで動作するようになる
  10. ローカルフォルダーに成果物だけ入ったイメージを出力する

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のような共通部分を複数回実行しなくて済むこともメリットと言えるかもしれない。

Playwrightの中華フォントを修正してNotoフォントにする