🐳

【Docker入門】Docker イメージレイヤーの構成原理

に公開

🐳 Docker イメージレイヤーの構成原理

🧭 概要

Dockerは効率的なビルドとキャッシュ活用のために、ファイルシステムの変更単位でイメージレイヤーを作成します。
ただし、すべてのDockerfile命令がレイヤーを生成するわけではなく、ファイルシステムに実際の変化があった場合のみです。


🧱 Dockerレイヤーとは?

  • Dockerは「イメージ=複数のレイヤーの集合体」として管理。
  • レイヤー単位でキャッシュを共有し、イメージの冗長を防ぎ、効率化を図る。
  • コンテナ実行時にも、レイヤーを積み重ね、最上部に書き込み可能なコンテナレイヤーをマウント。

🔗 UnionFS の役割

Dockerは「Union File System(UnionFS)」を使って、複数レイヤーを1つのファイルシステムのように見せます。

例:mount -t ufs -o upperdir=dir1,lowerdir=dir2,workdir=wrk -f myufs dirM
  • upperdir(上位ディレクトリ)が優先され、同一ファイルがある場合はそちらを採用。
  • OverlayFS, VFS, devicemapper などがサポートされ、主に OverlayFS が使われる。

📄 どの命令がレイヤーを作るのか?

命令 レイヤー生成 備考
FROM ✅(ベース) 既存イメージから開始。新規ではないがレイヤー構成に加わる。
LABEL メタデータ変更のみ。
COPY ファイル追加は新しいレイヤーとして扱われる。
RUN ファイルシステム変更があればレイヤー生成。
CMD 実行コマンドのメタデータのみ。

📎 ポイント:同じ RUN mkdir を何度も書いても、変化がなければ同じレイヤーIDになる場合もあるが、COPY は重複でも毎回新しいレイヤーが生成される傾向。


🧪 テスト結果まとめ

✔ 同一コマンドの繰り返し

RUN mkdir -p /test
COPY ./test.txt .
COPY ./test.txt .
RUN mkdir -p /test
  • mkdir は最初の1回以外、レイヤーが再利用されるケースあり。
  • COPY は毎回レイヤーが生成される(データが変わらなくても)。

✔ キャッシュ利用の挙動確認

  • 既存レイヤーが存在すれば "Using cache" と出力され、再ビルド不要。
  • レイヤーの差分は /var/lib/docker/overlay2diff/ として保存。

🧠 Dockerfile 最適化のポイント

❌ 非効率な例

RUN make /app
RUN rm -r $HOME/.cache
  • make のキャッシュは次のレイヤーに残り、イメージサイズ削減にならない。

✅ 効率的な例

RUN make /app && rm -r $HOME/.cache
  • 1レイヤー内でビルドとキャッシュ削除を完結させ、不要ファイルが残らない

📌 補足:Docker 23以降の変化

  • Docker 23 バージョンから、デフォルトビルダーが BuildKit に変更
  • buildx を使用するようになり、レイヤー構成やキャッシュ処理に違いが生じる可能性あり。

🔗 Docker Release Notes 23.0


📝 まとめ

  • Dockerはファイルシステムの差分ごとにレイヤーを構成し、キャッシュ効率・イメージサイズを最適化。
  • Dockerfileを記述する際は、レイヤー数を減らす工夫(複数命令の結合や不要ファイル削除)を行うことで、効率的な運用が可能。
  • バージョン差異やBuildKitの導入による仕様変更にも注意が必要。

Discussion