Dockerfileを設計していると、RUN命令の書き方次第でキャッシュや一時ファイルが最終イメージに混入し、予期せずサイズが膨らむことがあります。
docker image inspectではレイヤー構造の詳細は見えないため、どこが問題なのか特定が難しい。この記事では、Dockerイメージのレイヤーを対話型UIで可視化できるdiveコマンドの使い方を解説します。Rocky Linux 9.4 + Docker 26.1.4の実機で動作確認した、インストールから基本操作・問題パターンの発見・Dockerfile改善・CI組み込みまでをひとつの流れで紹介します。
この記事のポイント
・diveコマンドはDockerイメージのレイヤーをファイル単位で可視化するツール
・対話型UIで各レイヤーのファイル追加・削除・変更を確認できる
・効率スコアで「無駄なスペース」を数値化しDockerfile改善の優先度を把握できる
・--ciフラグでCIパイプラインへの組み込みが可能
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
diveとは何か
dive(ダイブ)は、DockerイメージのレイヤーをインタラクティブなターミナルUIで分析できるオープンソースのツールです。docker image historyコマンドでもレイヤーごとのサイズは確認できますが、「どのファイルが追加・変更・削除されたか」まではわかりません。diveはレイヤーを選択するとそのレイヤーで変更されたファイルツリーを表示するため、問題の所在を正確に把握できます。・可視化対象:イメージの各レイヤーとその差分ファイル
・主な用途:イメージサイズの肥大化原因の調査、中間レイヤーの不要ファイル特定
・出力形式:対話型UI(ターミナル)またはCI向けのレポート出力
・GitHub:wagoodman/dive(v0.12.0以降、Rocky Linux 9 / Ubuntu 24対応)
diveのインストール方法
1. Rocky Linux / RHEL系へのインストール
GitHub Releasesからrpmパッケージを取得してインストールします。# diveのバージョンを変数に設定 DIVE_VERSION=0.12.0 # rpmパッケージをダウンロード curl -L -o /tmp/dive.rpm \ https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.rpm # インストール sudo rpm -ivh /tmp/dive.rpm # バージョン確認 dive --version
dive 0.12.0
2. Ubuntu / Debian系へのインストール
DIVE_VERSION=0.12.0 curl -L -o /tmp/dive.deb \ https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.deb sudo dpkg -i /tmp/dive.deb dive --version
3. Dockerコンテナとして実行する
インストール不要で試したい場合は、コンテナとして実行できます。Dockerソケットのマウントが必要です。docker run --rm -it \ -v /var/run/docker.sock:/var/run/docker.sock \ wagoodman/dive:latest nginx:1.27-alpine
diveの基本的な使い方
1. 対話型UIを起動する
分析したいイメージ名またはIDを引数に渡して実行します。# ローカルイメージを分析 dive nginx:1.27-alpine # ビルドと同時に分析 dive build -t myapp:latest .
Image Source: docker://nginx:1.27-alpine Fetching image... (this can take a while for large images) Analyzing image... Building cache...
2. 画面の見方
diveのUIは左右2ペイン構成です。・左ペイン(Layers):FROM命令を起点にした各レイヤーの一覧。サイズとDockerfileの命令が表示される
・右ペイン(Current Layer Changes):選択中のレイヤーで変更されたファイルツリー。A(追加)・R(削除)・C(変更)のマーカー付き
・下部(Image Details):Total Image Size / Potential wasted space / Image efficiency scoreの3指標
主なキーバインドは以下のとおりです。
| キー | 操作 |
|---|---|
| Tab | 左右ペイン間の切り替え |
| ↑ / ↓ | レイヤー・ファイルの移動 |
| Space | ファイルツリーの展開/折りたたみ |
| Ctrl+F | ファイル名検索 |
| Ctrl+A | 変更ファイルのみ表示切り替え |
| Ctrl+Z | 変更種別(A/R/C)でフィルタ |
| Ctrl+C | 終了 |
3. 効率スコアの読み方
画面下部に表示される3つの指標が、イメージ改善の判断基準になります。・Total Image size:イメージ全体の圧縮前サイズ
・Potential wasted space:中間レイヤーで削除されたファイルなど、無駄に占有しているバイト数
・Image efficiency score:100%が理論上の最大効率。90%を下回るイメージは改善余地が大きい
Dockerハンズオン研修の詳細を見る >>
diveでよく見つかる問題パターン
1. パッケージマネージャのキャッシュが残っている
最もよく見られる問題です。yum installやapt-get installを単独のRUN命令で書くと、キャッシュファイルが別レイヤーに保存されます。次のRUN命令でキャッシュを削除しても、Dockerのレイヤー設計上、削除前のレイヤーはイメージに残り続けます。diveでこのパターンを発見した場合、左ペインでパッケージインストール命令のレイヤーを選択し、右ペインで
/var/cache/yumや/var/lib/apt/lists配下にファイルが残っていないか確認します。# 問題のあるDockerfile(キャッシュが別レイヤーに残る) RUN yum install -y curl RUN yum clean all # diveのImage Details欄(改善前) Potential wasted space: 42 MB Image efficiency score: 78 %
2. 中間レイヤーに秘密情報が残っている
ビルド時にトークンやAPIキーをRUN命令で渡した場合、そのレイヤーはイメージにそのまま記録されます。後のレイヤーで削除しても、docker history --no-truncやdiveでは復元可能な状態で残ります。diveの右ペインでCtrl+Fを使い、
.envや秘密鍵ファイル等が中間レイヤーに存在しないか確認します。発見した場合はRUN --mount=type=secretかマルチステージビルドへの移行が必要です。3. ビルドツールが最終イメージに含まれている
gcc、make、pip等のビルドツールは、コンパイルやパッケージインストールに使うだけで本番稼働には不要です。これらが最終イメージに含まれると、サイズが増加するだけでなく攻撃面も広がります。diveで
/usr/bin/gcc等のパスを右ペインで確認し、本番用の最終レイヤーに存在する場合はマルチステージビルドへの移行を検討します。diveの発見をDockerfileに反映する
1. RUN命令をチェーンして一時ファイルを同一レイヤーで削除する
パッケージインストールとキャッシュ削除を1つのRUN命令にまとめると、中間ファイルが別レイヤーに残りません。# 改善後のDockerfile(RUNをチェーンして同一レイヤーで削除) RUN yum install -y curl \ && yum clean all \ && rm -rf /var/cache/yum # diveのImage Details欄(改善後) Potential wasted space: 0 bytes Image efficiency score: 100 %
2. マルチステージビルドで解決する
ビルドツールが最終イメージに含まれる問題は、マルチステージビルドで根本解決できます。ビルドステージと実行ステージを分離し、実行ステージには成果物だけをコピーします。# ビルドステージ(ビルドツールを使い捨て) FROM golang:1.22-alpine AS builder WORKDIR /src COPY . . RUN go build -o /app ./cmd/server # 実行ステージ(バイナリだけをコピー) FROM alpine:3.20 COPY --from=builder /app /app CMD ["/app"]
# マルチステージ適用後のImage Details Total Image size: 8.1 MB ← ビルドステージ含む場合は380 MB Potential wasted space: 0 bytes Image efficiency score: 100 %
CIでdiveを自動実行する
--ciフラグを付けると、対話型UIを表示せず効率スコアの判定結果のみを出力し、閾値を超えた場合に終了コード1を返します。CIパイプラインでのゲートとして組み込むと、Dockerfileの品質劣化を自動検出できます。# CIモードで実行 dive --ci myapp:latest
efficiency: 98.4521 % wastedBytes: 142355 bytes (142 kB) userWastedPercent: 0.0000 % Result:PASS [Total:3] [Passed:3] [Failed:0] [Warn:0] [Skipped:0]
.dive-ciファイルで設定できます。# .dive-ci(YAMLフォーマット) rules: # 効率スコアが95%を下回った場合にNG lowestEfficiency: 0.95 # 中間レイヤーで削除されたファイルが10MB以上ならNG highestWastedBytes: 10000000 # ユーザーが引き起こした無駄が1%以上ならNG highestUserWastedPercent: 0.01
# .github/workflows/docker-lint.yml(抜粋) - name: Analyze image with dive run: | docker build -t myapp:ci . dive --ci myapp:ci
トラブルシュート
「cannot connect to the Docker daemon」が出るDockerソケットへのアクセス権がないか、dockerdが停止しています。
systemctl status dockerでdockerの起動状態を確認し、実行ユーザーがdockerグループに所属しているか確認してください。分析が途中で止まる(巨大イメージ)
1GB以上のイメージはキャッシュ構築に時間がかかります。
dive --source docker-archive myapp.tarでtarファイルを直接読み込むと安定する場合があります。--ciモードで常にFAILになる
.dive-ciの閾値が厳しすぎる可能性があります。まず--ciなしで対話型UIを起動し、実際のスコアを確認してから閾値を調整してください。本記事のまとめ
| やりたいこと | コマンド |
|---|---|
| ローカルイメージを対話型UIで分析 | dive イメージ名:タグ |
| ビルドと同時に分析 | dive build -t イメージ名:タグ . |
| コンテナで実行(インストール不要) | docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive:latest イメージ名 |
| CIモードで効率スコアを判定 | dive --ci イメージ名:タグ |
| 変更ファイルのみ右ペインに絞り込む | 対話型UI内でCtrl+A |
| ファイル名で検索 | 対話型UI内でCtrl+F |
Dockerハンズオン研修の詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Docker Swarmは今も選択肢になるか|Kubernetesとの違いを冗長化・運用負荷・撤退容易性で比べる
- この記事の属するカテゴリ:Dockerへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます