Docker layer キャッシュとは?なぜ 2 回目の build は速いのか
Docker layer キャッシュは、命令の入力が変わっていないときにその結果を再利用します。そのため、実際の変更より後のステップだけが再実行されます。
イメージを初めてビルドするとき、すべての layer はゼロから作られます。2 回目には、Docker が各命令をキャッシュと照合し、入力が同一の layer を再利用します。何がキャッシュを無効化するかを理解することは、高速な Docker build のための最も大きな単一のレバーです。
キャッシュの仕組み
Docker は Dockerfile を上から下へたどります。各命令について、命令とその入力(COPY の場合はファイルの内容)からキャッシュキーを計算します。キーがキャッシュされた layer と一致すればそれを再利用します。最初のミスがその layer とそれ以降すべてを無効化します。
連鎖のルール
キャッシュの無効化は連鎖します。5 行目が変わると、6 行目以降が手つかずでも 5 行目から末尾まで rebuild されます。だからこそ命令の順序がこれほど重要なのです。
キャッシュヒットのために並べる
めったに変わらないステップを先に、頻繁に変わるステップを後に置きます。コードの編集が依存関係の layer を壊さないよう、source をコピーする前に lockfile をコピーして依存関係をインストールしましょう。
エフェメラルな CI におけるキャッシュ
新しい CI runner は空のローカルキャッシュで始まるため、素朴な構成では毎回すべてを rebuild します。解決策には、registry ベースのキャッシュ(--cache-from)、BuildKit のキャッシュエクスポート、あるいは job 間でキャッシュを永続化する runner があります。
マネージド runner でのキャッシュ
Latchkey のマネージド runner は Docker layer キャッシュを job 間で温かく保つため、依存関係とベースの layer が rebuild されずに再利用されます - 数分かかる冷たい build を数秒に変えます。
重要なポイント
- layer は、その命令と入力が変わっていないときに再利用されます。
- 無効化は連鎖します - 1 行の変更がそれ以降すべてを rebuild します。
- エフェメラルな CI で恩恵を受けるには、外部または永続的なキャッシュが必要です。