diveとは
dive
は、Dockerイメージをレイヤーごとに分析するツール。
各レイヤーで追加・変更・削除されたファイルを確認できるほか、無駄なファイルによって肥大化した容量(Wasted Space)を検出できる。
インストール
Dockerイメージとして提供されているため、Dockerさえあればインストール不要で実行できる。
$ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive <イメージ名>
macOSの場合はHomebrewでインストールも可能。
$ brew install dive
基本的な使い方
分析したいイメージ名を指定して実行する。
$ dive node:20-alpine
起動するとTUI(ターミナルUI)が開き、左側にレイヤーの一覧、右側に選択中のレイヤーで変更されたファイルツリーが表示される。
ファイルツリーでは、追加されたファイルは+、削除されたファイルは-、変更されたファイルはΔのマークが付く。
画面下部にはイメージ全体のTotal Image sizeと、削除しても実行に影響しない無駄な容量を示すPotential wasted space、イメージの効率を示すImage efficiency scoreが表示される。
操作方法
TUIでは以下のキー操作が使える。
| キー | 機能 |
|---|---|
| Tab | レイヤー一覧とファイルツリーの切り替え |
| ↑↓ / J K | 1行ずつ移動 |
| PageUp/PageDown / U D | ページ単位で移動 |
| Ctrl+A | 集約された変更を表示(レイヤー一覧選択時) / 追加ファイルの表示切り替え(ファイルツリー選択時) |
| Ctrl+L | 現在選択中のレイヤーの変更のみ表示 |
| Space | ディレクトリの展開/折りたたみ |
| Ctrl+Space | すべてのディレクトリの展開/折りたたみ |
| Ctrl+F | ファイルをパスでフィルタリング |
| Ctrl+C | 終了 |
Ctrl+Aでレイヤーごとの変更ではなく、イメージ全体でファイルがどう変化したかを集約して確認できるため、どのレイヤーで肥大化したファイルが追加されたかを追いやすい。
無駄なレイヤーを検出する例
パッケージ追加・ファイルコピー・不要ファイル削除をそれぞれ別レイヤーで行う、以下のようなDockerfileで試す。
FROM alpine:3.20
RUN apk add --no-cache curl
COPY big-file.txt /big-file.txt
RUN rm /big-file.txt
RUN rmは最後のレイヤーでファイルを削除しているだけであり、COPYで追加したレイヤー自体にはbig-file.txtが残ったままである。
このイメージをdiveのCIモード(--ci)で確認すると、無駄な容量を検出できる。
$ dive dive-sample:latest --ci
Using default CI config
Image Source: docker://dive-sample:latest
Extracting image from docker-engine... (this can take a while for large images)
Analyzing image...
efficiency: 73.2271 %
wastedBytes: 5502580 bytes (5.5 MB)
userWastedPercent: 50.8104 %
Inefficient Files:
Count Wasted Space File Path
2 5.0 MB /big-file.txt
2 436 kB /etc/ssl/certs/ca-certificates.crt
2 44 kB /lib/apk/db/installed
2 22 kB /lib/apk/db/scripts.tar
2 288 B /lib/apk/db/triggers
2 123 B /etc/apk/world
Results:
FAIL: highestUserWastedPercent: too many bytes wasted, relative to the user bytes added (%-user-wasted-bytes=0.508103685810424 > threshold=0.1)
SKIP: highestWastedBytes: rule disabled
FAIL: lowestEfficiency: image efficiency is too low (efficiency=0.7322710060027512 < threshold=0.9)
Result:FAIL [Total:3] [Passed:0] [Failed:2] [Warn:0] [Skipped:1]
Inefficient Filesに/big-file.txtが2件表示されており、COPYで追加したレイヤーとRUN rmのレイヤーの両方に容量が残っていることが分かる。COPYとRUN rmを1つのレイヤーにまとめるか、そもそも不要なファイルをコピーしないようにDockerfileを修正すれば、無駄な容量を削減できる。
CIで自動チェックする(–ci)
--ciオプションを付けると、TUIを起動せずに分析結果を出力して終了する。
効率が閾値を下回った場合は終了コードが非0になるため、CIパイプラインに組み込んでイメージの肥大化を自動検知できる。
$ dive <イメージ名> --ci
閾値は--lowestEfficiencyや--highestUserWastedPercentで調整できる。
$ dive <イメージ名> --ci --lowestEfficiency=0.95 --highestUserWastedPercent=0.05
--ci-configオプションでYAMLファイルを指定すると、チェックルールをまとめて管理できる。
rules:
lowestEfficiency: 0.95
highestWastedBytes: 20MB
highestUserWastedPercent: 0.05
$ dive <イメージ名> --ci --ci-config .dive-ci.yaml
分析結果をJSONで出力する(–json)
--jsonオプションを付けると、レイヤーごとのファイル一覧や無駄な容量の情報をJSONファイルに出力できる。
$ dive <イメージ名> --json result.json
出力されるJSONにはイメージ全体の情報と、レイヤーごとの情報が含まれる。
{
"image": {
"sizeBytes": 135587976,
"inefficientBytes": 74804,
"efficiencyScore": 0.9996386478989848,
"fileReference": [
{
"count": 3,
"sizeBytes": 47207,
"file": "/lib/apk/db/installed"
}
]
},
"layer": [
{
"index": 0,
"sizeBytes": 8691209,
"command": "ADD alpine-minirootfs-3.23.4-aarch64.tar.gz / # buildkit"
}
]
}
fileReferenceには無駄になっているファイルの一覧、layerには各レイヤーのサイズと生成したコマンドが含まれており、他のツールと組み合わせて集計する用途にも使える。
参考
» dive
