概要



Dockerイメージをビルドしていると、意図せず容量が大きくなることがよくあります。そのほとんどの原因は 不必要に生成されたレイヤー にあります。この記事では docker history コマンドを使用してイメージの'系譜'を確認し、これを通じて実際のイメージを軽量化した最適化の経験を共有します。

このコマンドを活用すれば、何がイメージを重くしているのか正確に見つけ出し、より効率的なイメージを作成できます。


docker history: イメージの系譜を確認する

docker historyは特定のイメージがどのように作成されたのか、その構成履歴を表示するコマンドです。Dockerfileの各コマンドがどの レイヤー(layer) に積み重なっているのか、さらに各レイヤーが生成された時点と容量を確認することができます。

基本的な使い方は非常にシンプルです。

docker history [オプション] <イメージ名:タグ>

例えばローカルの my-app:latest イメージのヒストリーを確認するコマンドは次のようになります。

docker history my-app:latest

出力結果を見ると、イメージの一番上のレイヤー(最新)からベースイメージ(最も古い)まで順番に表示されます。

IMAGE          CREATED         CREATED BY                                      SIZE
a6215f271958   5 minutes ago   /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      7 weeks ago     /bin/sh -c #(nop) ADD file:f28242cf608f6...   7.81MB
  • CREATED BY: このレイヤーを生成したDockerfileコマンド

  • SIZE: 該当レイヤーが占める容量

役立つヒント: --no-truncでコマンド全体を見る

docker historyの基本出力は、CREATED BY列のコマンドが長すぎると途中で切れてしまいます。この時--no-truncオプションを併用すると、切れずに全コマンドを見ることができ、正確な分析に不可欠です。

docker history --no-trunc my-app:latest

レイヤー分析が重要な理由: 実際の最適化経験



DockerイメージはDockerfileの コマンド1行ごとに1つのレイヤー を生成することが基本原則です。そして各レイヤーは前のレイヤーの上に積み重なる'変更'です。

問題は、不必要にレイヤーを分けるとイメージ容量が急激に増加するということです。

事例: COPYRUN chownの罠

Dockerfileを書く際、プロジェクトファイルをコンテナにコピー(COPY)した後、該当ファイルの所有権を特定のユーザー(例: appuser)に変更(RUN chown)することがよくあります。

非効率的な方法: 2つのレイヤー

最初はDockerfileを次のように書きました。

# 1. ファイルを一旦コピー(root所有でコピーされる)
COPY . .

# 2. 所有権変更(別のコマンドで実行)
RUN chown -R appuser:appgroup /app

docker historyでビルドされたイメージの履歴を確認したところ、2つのレイヤーが作成されていました。

IMAGE          CREATED BY                                        SIZE
<layer_id_2>   /bin/sh -c chown -R appuser:appgroup /app        150MB  <-- (問題!)
<layer_id_1>   /bin/sh -c #(nop) COPY dir:abc in /app           150MB

ここで深刻な問題が発生します。

  1. COPY . . コマンドで150MBのファイルが レイヤー1 に追加されました。

  2. RUN chown コマンドは レイヤー1の150MBファイルをそのままコピー し、所有権情報だけを変更して レイヤー2 に新しく保存します。

ファイル内容は同じですが、一方は root 所有、もう一方は appuser 所有として、それぞれ異なるレイヤーに保存されることになり、結果的にこの2つのレイヤーだけでイメージ総容量は300MB(150MB + 150MB)になります。

効率的な方法: 1つのレイヤー

この問題は COPY コマンドの --chown フラグを使うことで簡単に解決できます。

# 1. コピーと同時に所有権指定
COPY --chown=appuser:appgroup . .

Dockerfileをこのように修正した後、docker historyで再度確認しました。

IMAGE          CREATED BY                                             SIZE
<layer_id_1>   /bin/sh -c #(nop) COPY --chown=appuser... dir:abc     150MB

1つのレイヤーが生成され、イメージの総容量は150MBに減少しました。たった2行のコマンドを1行にまとめただけで、イメージ容量が半分近く減ったのです。


結論

docker historyは単にイメージの生成履歴を見るだけでなく、 イメージ最適化のための重要な分析ツール です。

Dockerfileを修正した後は、習慣的に docker history --no-trunc を実行して、意図に沿ったレイヤーが生成されたか、不必要に容量を占めるレイヤーがないか確認することが重要です。この小さな習慣が積み重なり、軽量で効率的なイメージを作成できます。