ツール1つのバージョンを変えるだけでDockerのレイヤーが全部作り直しになる
Dockerfileでツールをインストールすると、途中のRUN命令でバージョンを1つ変えただけでも、それより上のレイヤーがすべて無効化されてビルドし直しになる。mise ociは、mise.tomlに書いたツールをそれぞれ独立したOCIレイヤーとしてビルドするコマンドである。ツール1つのバージョンを変えても、そのツールのレイヤーだけが再構築され、他のツールやベースイメージのレイヤーはそのまま再利用される。2026年9月時点では実験的機能に位置づけられている。
実験的機能を有効にする
mise ociの各サブコマンドは[experimental]と明記されており、MISE_EXPERIMENTAL=1またはmise settings experimental=trueで有効化する必要がある。有効化の方法は【mise】mise depsでロックファイルの更新を検知して依存関係を自動インストールする
と同じである。
$ MISE_EXPERIMENTAL=1 mise oci build
mise oci buildの基本
mise.tomlに書いたツールは、あらかじめmise installでローカルにインストールしておく。mise oci buildは、インストール済みのツールをOCIイメージのレイヤーとして詰め直すだけで、ツール自体のダウンロードは行わない。
[tools]
jq = "1.7.1"
$ mise install
$ mise oci build
mise pulling base image: debian:bookworm-slim
wrote OCI image layout to ./mise-oci
manifest: sha256:4beb502c...
tool layers:
jq@1.7.1 sha256:62193aa6a323 813658 bytes
出力先(デフォルトは./mise-oci)には、OCI image-layoutの仕様に沿ったblobs/・index.json・oci-layoutが生成される。skopeo・crane・podman loadといった他のツールでもそのまま扱える。-oで出力先、-tでイメージのタグ、--fromでベースイメージ(デフォルトはdebian:bookworm-slim)を変更できる。デフォルトではプロジェクトのmise.tomlに書いたツールだけが対象になり、~/.config/mise/config.tomlのような個人のグローバル設定にあるツールは含まれない。含めたい場合は--include-globalを付ける。
macOSでビルドすると動かないイメージができる
mise oci buildは常にLinux向けのイメージを作るが、macOS上で実行すると、ビルドに使うツールの実体もmacOS用のバイナリになってしまう。実行するとその旨の警告が表示される。
$ mise oci build
mise WARN building on macos host — 1 tool layer(s) contain macos binaries that will fail with `Exec format error` inside a linux container. Run `mise oci build` on a linux host (or in a linux container) for a working image.
mise WARN embedding a macos mise binary in a linux OCI image — it will fail at runtime. Run `mise oci build` on linux, or pass --no-mise to skip embedding.
実際にmacOS上でビルドしたイメージ内のツールを実行すると、Exec format errorになる。
$ mise oci run -- bash -c "jq --version"
mise built image: sha256:17498fee80d9...
bash: line 1: /mise/installs/jq/1.7.1/jq: cannot execute binary file: Exec format error
動くイメージを作るには、Linux環境(Dockerコンテナなど)でmise oci buildを実行する必要がある。mise本体のバイナリも同様にLinux向けのものが必要で、埋め込みたくない場合は--no-miseで埋め込み自体を省略できる。
ツールごとに独立したレイヤーになっていることを確認する
Linux環境でjq@1.7.1とjq@1.8.2それぞれをビルドし、生成されたblobを比較すると、バージョンを変えても再利用されるレイヤーと、変更のたびに作り直されるレイヤーが分かる。
$ comm -12 <(ls mise-oci-1.7.1/blobs/sha256 | sort) <(ls mise-oci-1.8.2/blobs/sha256 | sort)
32d322b19846...
74d289ece446...
75782e20ea1f...
7個中3個のblob(ベースイメージ本体とその周辺のレイヤー)が両方のビルドで共通しており、jqのツールレイヤー・イメージの設定・マニフェストだけがバージョンごとに作り直されている。DockerfileでRUNを積み重ねる場合と異なり、無関係なツールやベースイメージのレイヤーを巻き込まずに済む。
mise oci runでビルドしたイメージをその場で実行する
mise oci runは、ビルドしたイメージをDocker/Podmanにロードしてコマンドを実行するところまで1つのコマンドで行う。
$ mise oci run -it -- bash
Linux上でビルドした結果を再利用する場合は、--image-dirでビルド済みのイメージレイアウトを指定すると、ビルドをスキップしてロード・実行だけを行う。
$ mise oci run --image-dir ./linux-built -- jq --version
jq-1.7.1
実行後は、デフォルトでロードしたイメージがDocker/Podmanのストレージから削除される。ロードしたまま残しておきたい場合は--keepを付ける。
mise oci pushでレジストリに送る
mise oci pushは、mise組み込みのレジストリクライアントでOCIイメージをレジストリに送る。docker/podman本体は不要で、認証情報はdocker login/podman loginが使うものと同じ場所(~/.docker/config.jsonなど)から読み込む。ローカルに一時レジストリを立てて試すと、レジストリ未認証でもそのまま送れることを確認できる。
$ mise oci push --image-dir ./linux-built localhost:5555/demo:latest
pushed sha256:4beb502c... to localhost:5555/demo:latest (5 blob(s) uploaded, 0 already present)
変更が無いまま再度pushすると、レジストリに既にあるblobはアップロードされない。
$ mise oci push --image-dir ./linux-built localhost:5555/demo:latest
pushed sha256:4beb502c... to localhost:5555/demo:latest (0 blob(s) uploaded, 5 already present)
--image-dirを省略すると、現在のmise.tomlからビルドしてそのままpushする。CIのように毎回タグが変わる運用では、--cache-fromで直前にpushしたイメージを指定すると、変わっていないツールのレイヤーを再ビルド・再アップロードせずに済む。
