ソフトウェアの作成時における悩ましい問題のひとつが
mkosiとは
「mkosi」
- UbuntuやFedoraを含むさまざまなディストリビューションのルートファイルシステムに対応
- 個々のリリースやCPUアーキテクチャーを指定できる
- 起動可能な仮想マシンイメージだけでなく、コンテナー用のルートファイルシステムをアーカイブしたものも作れる
- コマンドラインオプションを設定ファイル化することでリポジトリでも管理しやすくなっている
- ソフトウェアのビルドを行うスクリプトを設定ファイルに記述可能
- 「ビルド用イメージ」
「動作確認用イメージ」 に分けることで、それぞれを独立して運用できる - SecureBootやTPMに対応したイメージも作れる
- 作成するイメージそのものを暗号化することも可能
systemdと同様に、ひとつのコマンドに様々な機能を備えています。使い方を覚えるのはなかなか骨が折れる作業になりますが、一度設定ファイルを作り込んでしまえばあとはそれを流用するだけで済みます。
仕組み上はクロスディストリビューションにも対応しています。つまりUbuntu上でFedoraのイメージを作ったり、Fedora上でopenSUSEのイメージを作ることが可能です。ただしそのためには、それぞれのディストリビューションで必要なソフトウェアをインストールする必要があります。その手間を考えると、実際に運用する際は、基本的にホストと同じディストリビューションの作成だけを考えたほうが良いでしょう[1]。
mkosiのインストール方法
実際にmkosiをインストールしてみましょう。今回はUbuntu 24.
$ sudo apt install mkosi systemd-ukify (中略) The following NEW packages will be installed: archlinux-keyring augeas-lenses binutils binutils-common binutils-x86-64-linux-gnu bubblewrap build-essential bzip2 cpp cpp-13 cpp-13-x86-64-linux-gnu cpp-x86-64-linux-gnu debian-archive-keyring debugedit deltarpm dnf dnf-data dpkg-dev erofs-utils fakeroot g++ g++-13 g++-13-x86-64-linux-gnu g++-x86-64-linux-gnu gcc gcc-13 gcc-13-base gcc-13-x86-64-linux-gnu gcc-x86-64-linux-gnu libalgorithm-diff-perl libalgorithm-diff-xs-perl libalgorithm-merge-perl libalpm13t64 libasan8 libatomic1 libaugeas0 libauthen-sasl-perl libbinutils libboost-thread1.83.0 libcc1-0 libclone-perl libcomps0 libctf-nobfd0 libctf0 libdata-dump-perl libdnf2-common libdnf2t64 libdpkg-perl libencode-locale-perl libevent-2.1-7t64 libfakeroot libfile-fcntllock-perl libfile-listing-perl libfont-afm-perl libfsverity0 libgcc-13-dev libgomp1 libgprofng0 libhtml-form-perl libhtml-format-perl libhtml-parser-perl libhtml-tagset-perl libhtml-tree-perl libhttp-cookies-perl libhttp-daemon-perl libhttp-date-perl libhttp-message-perl libhttp-negotiate-perl libhwasan0 libio-html-perl libio-socket-ssl-perl libisl23 libitm1 liblsan0 liblua5.3-0 liblwp-mediatypes-perl liblwp-protocol-https-perl libmailtools-perl libmodulemd2 libmpc3 libnet-http-perl libnet-smtp-ssl-perl libnet-ssleay-perl libnss-mymachines libpkgconf3 libprotobuf-lite32t64 libproxy1v5 libquadmath0 librepo0 librpm9t64 librpmbuild9t64 librpmio9t64 librpmsign9t64 libsframe1 libsigc++-2.0-0v5 libsolv-tools libsolv1 libsolvext1 libstdc++-13-dev libtext-unidecode-perl libtimedate-perl libtry-tiny-perl libtsan2 libubsan1 libunbound8 liburi-perl libwww-perl libwww-robotrules-perl libxml-libxml-perl libxml-namespacesupport-perl libxml-parser-perl libxml-sax-base-perl libxml-sax-expat-perl libxml-sax-perl libyaml-cpp0.8 libzypp-bin libzypp-common libzypp-config libzypp1722 lto-disabled-list make makepkg mkosi ovmf pacman-package-manager perl-openssl-defaults pkgconf pkgconf-bin python3-dnf python3-gpg python3-hawkey python3-libcomps python3-libdnf python3-pefile python3-rpm python3-unbound rpm rpm-common rpm2cpio sqlite3 systemd-container tex-common texinfo texinfo-lib zypper zypper-common (後略)
「systemd-ukify」
mkosiそのものはPythonスクリプトとして作られています。よって最低限必要なものは、Pythonの実行環境と、systemd-container
ただし様々なディストリビューションのルートファイルシステムを作るという特性上、Ubuntu上でインストールできるたくさんのパッケージ管理システムにも入れようとします。具体的にはdnfやpacman、zypperなどのコマンド類は、実はUbuntuでもインストールできるのです。
さらにUEFI/--no-install-recommends
」
mkosi本体はPythonソフトウェアであるため、pipxコマンドを使えば最新版をインストールできます。
$ pipx install git+https://github.com/systemd/mkosi.git
Ubuntuのリポジトリにあるバージョンでは古くて必要な機能が足りない場合は、こちらの方法でインストールしてください。ただし、pipxでインストールする場合、必要なコマンド類は別途手動でインストールしなくてはなりません。それが面倒であれば、mkosiパッケージをインストールした上で、pipxでインストールすれば大体のものは揃います[3]。
mkosiの簡単な使い方
mkosiを実際に使うには、さまざまなオプションを指定しなくてはなりません。何も指定せずに実行すると、ホストのイメージを作ろうとします。ちなみにこのあたりの初期設定値は
$ mkosi summary IMAGE: default CONFIG: Profile: none Include: none Initrd Include: none Images: none Dependencies: none Minimum Version: none DISTRIBUTION: Distribution: ubuntu Release: noble Architecture: x86-64 Mirror: default Local Mirror (build): none Repo Signature/Key check: yes Repositories: none Use Only Package Cache: no Package Manager Trees: none OUTPUT: Output Format: disk Manifest Formats: (none) Output: image.raw Compression: none (後略)
空のイメージを作る
何もオプションを指定せずに実行すると、上記の設定に合わせたイメージが作られます。なお、管理者権限が必要です。
$ sudo mkosi ‣ Building default image ‣ Installing Ubuntu (中略) All done. ‣ Formatting ESP/XBOOTLDR partitions Automatically determined minimal disk image size as 131.2M, current image size is 131.2M. File '/var/tmp/mkosi-workspacenhe5nruo/staging/image.raw' already is of requested size or larger, not growing. (131.2M >= 131.2M) No changes. ‣ /home/ubuntu/image.raw size is 131.3M, consumes 130.3M. $ ls -lh total 131M lrwxrwxrwx 1 ubuntu ubuntu 9 Feb 24 08:46 image -> image.raw -rw-r--r-- 1 ubuntu ubuntu 132M Feb 24 08:46 image.raw $ file image.raw image.raw: DOS/MBR boot sector; partition 1 : ID=0xee, start-CHS (0x0,0,2), end-CHS (0x3ff,255,63), startsector 1, 268815 sectors, extended partition table (last)
具体的には次のようなフォーマットで作られます。
- ext4でフォーマットされた単一パーティションのイメージファイル
- Ubuntuの最小限のルートファイルシステム
- アカウントはrootだけ
- カーネルやsystemdがインストールされないため、QEMUによる起動はできない
このイメージにログインするにはshellサブコマンドを実行します。
$ sudo mkosi shell root@default:~# dpkg -l | wc -l 65 root@default:~# apt -bash: apt: command not found
これは何をしているのかと言うと、単にbwrapでコンテナー環境を構築し、そこからsystemd-nspawnで作成したイメージを指定してログイン
このイメージの中に、パッケージは最低限のものしか入っていません。カーネルやsystemdはおろか、aptコマンドも入っていません。よって起動イメージとしては使えませんし、パッケージの追加もできません。これはmkosiに-p パッケージ名
」
パッケージを追加して作り直す
そこで試しにUbuntuのベースシステムには基本的に入っている-o ubuntu1
」
$ sudo mkosi -p ubuntu-minimal -p ubuntu-standard -o ubuntu1 shell (中略) ‣ /home/ubuntu/test4/ubuntu1.raw size is 505.3M, consumes 504.3M. root@default:~# dpkg -l | wc -l 241 root@default:~# apt --version apt 2.7.14 (amd64) root@default:~# systemctl --version systemd 255 (255.4-1ubuntu8.5) (中略)
ここではいきなりshellコマンドを指定しています。mkosiはサブコマンドを指定しなければ暗黙で-o
」-o ubuntu1
」
インストールされるパッケージとサイズがだいぶ増えました。Ubuntuのルートファイルシステムとしてインタラクティブに使う予定がなければ、ubuntu-standardはインストールしなくても良いでしょう。
rootパスワードを設定する
shellサブコマンドはコンテナーの中で指定したコマンド
ただしbootコマンドを実行する場合はログインできなくてはなりません。mkosiで作ったイメージに一般ユーザーは存在せず、rootもパスワードが無効化されているためログインできません。そこで今回はrootのパスワードを設定してしまいましょう。
root@default:~# passwd New password: Retype new password: passwd: password updated successfully root@default:~# exit
もちろんrootパスワードを設定せずにユーザーを追加するほうが良いでしょう。
作成したイメージをシステムコンテナーとして起動する
一度shellを抜けて、今度はbootコマンドで起動します。
$ sudo mkosi -o ubuntu1 boot (中略) Starting systemd-update-utmp-runlevel.service - Record Runlevel Change in UTMP... [ OK ] Finished systemd-update-utmp-runlevel.service - Record Runlevel Change in UTMP. Ubuntu 24.04.2 LTS default pts/0 default login: root Password: Welcome to Ubuntu 24.04.2 LTS (GNU/Linux 6.8.0-53-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. root@default:~#
無事に起動できました。ただしこの方法は
コンテナーを終了するにはpoweroffコマンドを実行するだけです。
root@default:~# poweroff (中略) Sending SIGTERM to remaining processes... Sending SIGKILL to remaining processes... All filesystems, swaps, loop devices, MD devices and DM devices detached. Powering off.
ちなみに]
を3回入力」
mkosi.confを作成する
mkosiはとても複雑で多種多様なオプションを持っています。これを実行の度に指定するのは大変です。カレントディレクトリもしくは--directory
」mkosi.
」
たとえば前項のオプションに似た内容を設定ファイルに書き下すと次のようになります。
[Distribution]
Distribution=ubuntu
[Output]
Format=disk
Output=ubuntu2
[Content]
Packages=ubuntu-minimal
これまでとはオプションをいくつか変更しています。出力ファイルを前のそれとかぶらないように
この状態でmkosi summary
」mkosi.
を更新した場合は、まず期待通りの設定になっているかをmkosi summary
」
さらに情報を追加して複雑な設定にしてみましょう。
[Distribution]
Distribution=ubuntu
Release=plucky
[Output]
Format=disk
Output=ubuntu2
CacheDirectory=cache
[Content]
Packages=ubuntu-minimal
Hostname=plucky
ここでは2025年4月にリリースされたUbuntu 25.
$ sudo mkosi (中略) ‣ /home/ubuntu/test4/ubuntu2.raw size is 390.2M, consumes 389.3M.
ちなみにCacheDirectoryで指定したディレクトリにはdebファイルとリポジトリのメタデータが保存されます。
フックスクリプトを活用して任意のプログラムをビルドする
mkosiの主要な目的のひとつが
mkosiでは、これをよりクロスプラットフォームに対応させる形で実現しています。つまり、mkosi.
さて、mkosiにおけるビルド環境はフックスクリプトを使うことで次のように実現します。
- パッケージインストール後など環境の準備が整ったあとの微調整
(mkosi. prepare) - イメージの元となるシステムができたあとのソフトウェアビルド処理の実行
(mkosi. build) - ソフトウェアのビルドとインストール後の後処理
(mkosi. postinst) - イメージ作成直前の微調整
(mkosi. finalize)
たとえば
$ git clone https://git.savannah.gnu.org/git/hello.git $ cd hello
移動したディレクトリに次のmkosi.
[Distribution]
Distribution=ubuntu
Release=plucky
[Output]
Format=disk
Output=ubuntu2
CacheDirectory=cache
[Content]
Packages=ubuntu-minimal
BuildPackages=build-essential,automake,git,wget,ca-certificates,autopoint,gperf,help2man,texinfo
Hostname=plucky
WithNetwork=true
これまでとの違いは
「BuildPackages」
とはいえ最初のうちは何をインストールすれば良いかわからないはず。その場合は、後述のmkosi.
」bash
」
mkosiは初期設定だと安全のため、外部ネットワークは利用できません。つまり追加ライブラリのダウンロードが阻害されてしまうため、ここではWithNetwork=true
」
さらに次のようなmkosi.
」
#!/bin/sh
if [ "$container" != "mkosi" ]; then
exec mkosi-chroot "$CHROOT_SCRIPT" "$@"
fi
./bootstrap
./configure
make
make install
ポイントはifブロックの部分です。これをやっておかないと、せっかくインストールしたautomake等のコマンドが使えません。あとはビルドしたいソフトウェアに応じて実行するスクリプトを変えれば良いでしょう。
$ chmod +x mkosi.build
これで準備が完了です。mkosiは、mkosi.
$ sudo mkosi ‣ Building default image ‣ Installing Ubuntu (中略) ‣ Running build script /home/ubuntu/temp/hello/mkosi.build… ./bootstrap: Bootstrapping from checked-out hello sources... ./bootstrap: getting gnulib files... (中略) make[2]: Leaving directory '/work/src' make[1]: Leaving directory '/work/src' ‣ Copying in build tree… (中略) No changes. ‣ /home/ubuntu/temp/hello/ubuntu2.raw size is 390.5M, consumes 389.5M.
これでビルドは完了しました。GNU helloの場合はカレントディレクトリにhelloコマンドがインストールされているはずですので実行してみましょう。
$ ./hello Hello, world!
ちなみにmkosi.
ではmake install
」
$ sudo mkosi shell root@default:~# /usr/local/bin/hello Hello, world!
mkosiはsystemdと同じく