Dockerイメージとレイヤー内容を探索するツール「Dive」
(github.com/wagoodman)- Diveは、Docker/OCIイメージのレイヤーとファイル内容を探索し、イメージサイズを削減できる余地を見つけるためのツール
- イメージタグ・ID・ダイジェストを指定して
dive <your-image-tag>を実行するか、dive build -t <some-tag> .でビルド直後の分析まで一度に実行できる - レイヤーを選択すると、そのレイヤーと前のレイヤーを結合したファイルツリーが表示され、追加・変更・削除されたファイルと累積変更をファイルツリーで確認できる
- 実験的な image efficiency 指標により、重複ファイル、レイヤー間でのファイル移動、完全に削除されていないファイルによって発生した無駄な領域をスコアと総容量で推定する
CI=trueでUIをスキップし、イメージ効率・無駄領域の基準に応じて pass/fail を返せるため、CIパイプラインでイメージサイズ管理を自動化できる
Diveができること
- Diveは、Dockerイメージ、レイヤー内容、Docker/OCIイメージのサイズを削減する方法を探索するツール
- 基本的な実行方法は、イメージタグ・ID・ダイジェストを渡す形式
dive <your-image-tag>
- Dockerコンテナとして実行することもでき、その場合はDockerソケットをマウントする必要がある
docker.io/wagoodman/diveイメージを使用- 対象イメージの例として
nginx:latestが示されている
- イメージをビルドした直後に分析したい場合は、
docker buildの代わりに同じ形式のdive buildコマンドを使えるdive build -t <some-tag> .
- macOSでビルド分析をコンテナとして実行する方式は、Dockerコンテナエンジンのみをサポートする
- プロジェクトの状態は beta quality で、新機能要望やバグは issue として提出できる
レイヤーとファイル変更の探索
- 左側でレイヤーを選ぶと、右側にそのレイヤーと前のレイヤーを結合したファイルツリーが表示される
- 方向キーでファイルツリーを移動できる
- 各レイヤーで変更されたファイルの状態がファイルツリーに表示される
- 変更あり
- 修正済み
- 追加済み
- 削除済み
- 変更表示の方式は、特定レイヤー基準またはそのレイヤーまでの累積変更基準に切り替えられる
イメージ効率と無駄領域の推定
- 左下パネルには基本的なレイヤー情報と実験的な image efficiency 指標が表示される
- この指標はイメージ内の無駄な領域を推定する
- レイヤー間のファイル重複
- レイヤー間でのファイル移動
- 完全に削除されていないファイル
- 結果は百分率の score と、無駄になったファイル領域の総量として提供される
CIで pass/fail 基準として利用
CI=true環境変数を指定して実行すると、Dive UIをスキップしてイメージを分析し、終了コードとして pass/fail 結果を返す- リポジトリルートの
.dive-ciファイルで3つの基準を設定できるlowestEfficiency: 効率が指定割合より低いと失敗highestWastedBytes: 無駄領域が指定容量以上だと失敗highestUserWastedPercent: ユーザーレイヤー基準の無駄割合が指定値以上だと失敗
highestUserWastedPercentの計算では、base image layer はイメージ全体サイズに含まれない- CI設定ファイルのパスは
--ci-configオプションで上書きできる
イメージソースとコンテナエンジン
--sourceオプションで、コンテナイメージを取得する場所を選択できるdive <your-image> --source <source>dive <source>://<your-image>
- サポートされる
sourceオプションは以下の通りdocker: Docker engine、デフォルトdocker-archive: ディスク上の Docker Tar Archivepodman: Podman engine、Linuxのみ対応
インストールと実行方法
- Ubuntu/Debian では
.debパッケージまたは Snap でインストールできる - Snap方式は Docker を
apt-getでインストールした場合には推奨されず、既存の Docker daemon を壊す可能性があるという注意がある - RHEL/Centos では
.rpmパッケージでインストールできる - Arch Linux では extra repository で提供されており、pacman でインストールできる
- macOS では Homebrew、MacPorts、または releases page の Darwin ビルドでインストールできる
- Windows では Chocolatey、scoop、
winget、または releases page の Windows ビルドでインストールできる - Goツールとしてインストールするには Go 1.10 以上が必要
go install github.com/wagoodman/dive@latest- この方法でインストールすると、
dive -v実行時に正しいバージョンが表示されない
- Nix/NixOS と x-cmd によるインストール方法も提供されている
- Dockerイメージとして実行する場合は、Dockerソケットファイルを含める必要がある
-v /var/run/docker.sock:/var/run/docker.sock
- ローカルの Docker バージョンによっては、
DOCKER_API_VERSION=1.37のような環境変数が必要になる場合がある - Colima のような代替ランタイムを使う場合、ローカルイメージを取得するために
DOCKER_HOST環境変数の指定が必要になることがある
操作とUI設定
- 主なキーバインドでは、レイヤー表示とファイルツリー表示を切り替えながら、移動・フィルタリング・表示トグルを行える
Ctrl+CまたはQ: 終了Tab: レイヤー表示とファイルツリー表示の切り替えCtrl+F: ファイルフィルタCtrl+A: レイヤー表示では累積イメージ変更表示、ファイルツリー表示では追加ファイル表示のトグルCtrl+L: 現在のレイヤー変更表示Ctrl+R,Ctrl+M,Ctrl+U: 削除・修正・変更なしファイルの表示トグルCtrl+B: ファイル属性表示のトグル
- 個別設定は不要だが、YAML設定ファイルで値を上書きできる
- 設定可能な項目には、コンテナエンジン、イメージアーカイブ解析エラーの無視可否、ログ、キーバインド、diff表示、ファイルツリー幅、ディレクトリのデフォルト折りたたみ状態、レイヤー累積変更表示が含まれる
- 設定ファイルの検索場所は以下の通り
$XDG_CONFIG_HOME/dive/*.yaml$XDG_CONFIG_DIRS/dive/*.yaml~/.config/dive/*.yaml~/.dive.yaml
.yamlの代わりに.yml拡張子も使用できる
1件のコメント
Hacker News のコメント
イメージとレイヤーを扱うなら crane が優れていて、基盤ライブラリの go-containerregistry も良い
既存イメージに新しいレイヤーを追加したり、メタデータ(env vars、labels、entrypoint など)を変更したりでき、複数レイヤーのイメージを単一レイヤーに「平坦化」することもできる
また、変更内容を新しいベースイメージに再適用する「rebase」も可能で、これらすべてをレジストリ上で直接処理するため Docker は不要
https://github.com/google/go-containerregistry/blob/main/cmd...
craneという名前で提供されているそのおかげで、Nix でビルド用の依存関係(例: Go)だけでなく、パッケージング・デプロイ用ツール(例: gnu tar、crane)まで一緒に管理できる
dive は、Docker イメージがどう動作するのか、効率的な Dockerfile をどう書くのかを理解するのに本当に役立った
ドキュメントを読むことも重要だが、Dockerfile を変更した後に結果のレイヤー構造がどう変わるのかを直接見ることが、理解には決定的だった
Dive は素晴らしい。こうしたツールは、自分が正確に何をビルドしデプロイしているのかを学び、確信するうえで重要
Dredge も見る価値のあるツールで、レイヤー差分を比較するときに使っている
https://github.com/mthalman/dredge/blob/main/docs/commands/i...
https://blog.haschek.at/2019/the-curious-case-of-the-RasPi-i...
愚かな質問かもしれないが、なぜほとんどのコンテナ・インフラ系ツールが Go で書かれているのか気になる
Docker、Podman、nerdctl、Terraform、Kubernetes が思い浮かぶが、こうしたツールを作るうえで Go が提供する明確な利点があるのか知りたい
Go で書き直した主な理由は、当時(2012年)伸びていた Go の人気に乗るためだった。その場にいた
Docker と Kubernetes が別の人気言語で書かれていたと想像してみると、その違いが見えてくる
成熟した現代的な代替としては Rust くらいしか見当たらない
社内チームに Go エンジニアが多いのも同じ理由
さらにエコシステム効果もあり、他の実装のパッケージをコードの一部にそのまま活用できる
Dive が好きで、月に何度もツールボックスから取り出して使っている
ただ、選択したファイルの内容をすぐ見る方法があるのか気になる。レイヤー内にファイルが存在することを確認した後、その中身を見たいことが多いが、今はたいていコンテナを実行して
catを使うか、内容を抽出してからフォルダを探して入っているcatを使うのと大きくは変わらないいくつもの公開 Docker コンテナを拡張するとき、中で何をしているのか調べる過程で Dive に何度も救われた
本当に A+ 級のソフトウェア
dive のような優れたターミナル TUI ツールは他にもある。lazydocker と dry が思い浮かぶ
Docker カテゴリにもいくつかある
[0] https://terminaltrove.com/
確認してみるとレイヤーは見られるが、各レイヤーのコマンドだけを表示する
Dive はコンテナ/Docker 領域で驚くべきツール。コンテナの中に実際に何が入っているのかをデバッグするのがずっと楽になる
Depot [0] を始めた当初、イメージサイズを減らしビルドを速くする方法をよく質問されたので、Dive でその問題を解決する方法を短い記事 [1] にまとめた。今では少し古くなっているかもしれないが、誰かの役に立つかもしれない
Dive に着想を得て、各ビルドごとにビルドコンテキストの中に実際に何があるのかもより簡単に見えるようにし、数週間前に Depot の機能としてリリースした
[0] https://depot.dev
[1] https://depot.dev/blog/reducing-image-size-with-dive
[2] https://depot.dev/blog/build-context
Dive には非常に便利なこと以外にも、過小評価されている長所がある。作者が素晴らしい開発者で、一緒に仕事をするのが本当に楽しい人だということ
Google の container-diff というツールも本当に便利
bash にパイプして実行するよう勧められている任意のスクリプトが、システムに何をするのか確認するときに使っている
コンテナアプリやイメージに統合テストを実行するのに便利な方法
こうした Google のオープンソースプロジェクトは、元々管理していた人たちが多く去ってしまい、手が必要なようで残念。可能なときは PR を送り、時々 issue も閉じるようにしている。特にこのテストツールは、社内で維持しなければならない多数のベースイメージを扱う際に正気を保つうえで非常に貴重