Skip to main content

第25章:CIで速くする①:GitHub Actionsのビルドキャッシュ 🧪🏎️

CIが遅い最大の理由はシンプルで、毎回まっさらな環境で docker build が走るからです😇 ローカルだと効いてた“レイヤーキャッシュ”が、CIでは毎回ゼロに戻りがちなんですよね💦

この章では、GitHub Actions上でもDockerのビルドキャッシュ(レイヤーキャッシュ)を持ち回って速くする方法を、コピペで動く形まで落とし込みます✂️📦


✅ 学ぶこと(この章のゴール)🎯

  • GitHub Actionsで Dockerビルドキャッシュを永続化して、2回目以降を爆速にする⚡️
  • いちばん簡単な type=gha(GitHub Actions Cache backend) を使いこなす🧰
  • 「キャッシュが効かない典型」 を先に潰せるようになる🔨

type=gha はDocker Build/BuildKit側の仕組みで、GitHub Actionsのキャッシュ基盤を使います(しかもワークフローはかなり短い!)(Docker Documentation)


1) まず全体像:CIで“何をキャッシュするか”🧠🗺️

キャッシュには大きく2種類あります👇

  • A. レイヤーキャッシュ(Dockerfileの各ステップの結果) 🧱 → RUN npm ci とか RUN npm run build を“前回の結果”でスキップできる
  • B. キャッシュマウント(RUN --mount=type=cache で作るDLキャッシュ等) 🧠 → 依存DLなどをさらに速くする系(次章で本格的にやるやつ!) ※ただし、GitHub Actionsではキャッシュマウントがそのまま残らないケースがあるので、別の工夫が必要になります(Docker Documentation)

この章は A(レイヤーキャッシュ)をCIに持ち込むのが主役です🏁


2) いちばん簡単で強い:type=gha(GitHub Actionsのキャッシュに保存)🏎️💨

やることは基本これだけ👇

  • cache-from: type=gha(前回キャッシュを読む)
  • cache-to: type=gha,mode=max(今回キャッシュを保存する)

ポイントは mode=max! デフォルトが min だと“最終イメージ中心”になって、中間ステージのキャッシュが薄くなりがちです😵‍💫(Docker Documentation)

あと大事なのがこれ👇 type=ghaデフォルトの docker driver だと非対応なので、Buildx(BuildKitコンテナ)を使うのが基本です🐳(Docker Documentation)


3) コピペで動く:ビルドだけ(PRでも安全)✅🧪

まずは「ビルドするだけ」版から! PRでも動くし、キャッシュ効果もすぐ見えます👀✨

name: ci-docker-cache

on:
pull_request:
push:
branches: [ main ]

jobs:
docker-build:
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v5

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build (with GHA cache)
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: false
tags: myapp:ci
# ✅ 前回のキャッシュを読む
cache-from: type=gha,scope=myapp
# ✅ 今回のキャッシュを保存(重要:mode=max)
cache-to: type=gha,mode=max,scope=myapp
  • docker/build-push-action@v6 がBuildx/BuildKitを使ったビルドの定番です(GitHub)
  • scope を付けると、複数イメージをビルドしてもキャッシュが上書きされにくいです(デフォだと最後のビルドが勝ってしまう)(Docker Documentation)
  • キャッシュは 「今のブランチ / ベースブランチ / デフォルトブランチ」 の範囲で参照できる制限があります(これ知らないとハマる!)(Docker Documentation)

4) さらに実戦:pushする(GHCR/Docker Hubなど)📦🚀

本番運用なら「mainにpushされたらレジストリへpush」が王道です🏁 login を足して push: true にするだけ。

name: release-image

on:
push:
branches: [ main ]

jobs:
docker-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # GHCRへpushするなら必要

steps:
- uses: actions/checkout@v5

- uses: docker/setup-buildx-action@v3

- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build & Push (with GHA cache)
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/${{ github.repository }}:latest
cache-from: type=gha,scope=myapp
cache-to: type=gha,mode=max,scope=myapp

ここまでで「CIが遅い」をかなり潰せます💪🔥


5) “効かない/遅い”ときのチェックリスト 🕵️‍♂️✅

(1) mode=max 入れた?(超ありがち)🧨

入れないと「思ったより効かない…」になりやすいです😇(Docker Documentation)

(2) Buildxを使ってる?(driver問題)🐳

type=gha はデフォルトの docker driver だとダメで、Buildx前提です(Docker Documentation)

(3) 複数イメージを同じ scope で回してない?🧩

同じ scope だと、最後のビルドがキャッシュを上書きします。 イメージごとに scope を分けると安定します(Docker Documentation)

(4) ブランチ制限で“見えないキャッシュ”になってない?🌿

キャッシュ参照には制限があり、別ブランチのキャッシュが読めないケースがあります(Docker Documentation)

(5) キャッシュの上限/保持期間で消えてない?🧹

GitHub側の設定で、キャッシュは

  • デフォ7日保持
  • デフォ総量10GB(超えると古いものから追い出される) みたいな挙動になります(GitHub Docs) しかも最近は「10GB超え」も設定できるけど、プランや課金条件が絡みます(The GitHub Blog)

6) GitHub Actions側の“上限”ざっくり知識 🧠📏

  • キャッシュの保持やサイズは、リポジトリ設定から調整できます(保持日数・上限GB)(GitHub Docs)
  • キャッシュ操作はレート制限もあります(アップロード回数など)(GitHub Docs)
  • type=gha はDocker側でも “APIの混雑でタイムアウト” を起こすことがあり、トークンを渡すと軽減できる場合があります ※ docker/build-push-action なら secrets.GITHUB_TOKEN が自動で使われます。必要ならカスタムトークンも指定できます(Docker Documentation)

7) 🧪 ミニ演習:キャッシュ有/無でCI時間を比べよう📊⏱️

目標:「2回目が速い」を数字で体感する

  1. さっきの workflow を入れて、main にpush(or 手元でPR作って実行)🚀

  2. Actionsのログで、ビルド時間をメモ📝

  3. 同じコミットで、もう一回走らせる(Re-run jobs)🔁

  4. 2回目のログで CACHED が増える/処理が飛ぶのを確認👀

  5. 追加チャレンジ🔥

    • README だけ変更 → ほぼ全部キャッシュで終わるはず✌️
    • package-lock.json を変更 → npm ci 付近がやり直しになるはず💥(正常!)

8) 🤖 AI活用(Copilot / Codex向け)プロンプト集 🧰✨

そのまま貼れる形で置いとくよ〜😊🧠

✅ ①「キャッシュが効かない原因」特定プロンプト

GitHub Actions の Docker ビルドが遅いです。
以下の workflow と Dockerfile を見て、
キャッシュが効かない原因になりそうな点を「優先度順に3つ」挙げてください。
また、各原因に対して最小の修正案(差分イメージ)もください。

--- workflow ---
(ここにYAML)

--- Dockerfile ---
(ここにDockerfile)

✅ ② scope設計(モノレポ/複数イメージ)

このリポジトリで Docker イメージを複数ビルドします。
GitHub Actions の type=gha キャッシュを使う前提で、
scope の命名ルール案を3つ出して、メリデメも説明してください。

✅ ③ “速いのに壊れない”安全チェック

この workflow はキャッシュを使っています。
セキュリティや再現性(意図せず古いものを使う等)の観点で、
注意点チェックリストを作ってください。
「すぐ直せる改善」も提案してください。

9) 次につながる一言 🏁✨

この章で レイヤーキャッシュ はCIに持ち込めました🎉 次は、RUN --mount=type=cache“依存DLキャッシュ”をCIでも残す(さらに速くする)に進むと、体感もう一段上がります⚡️😆(Docker Documentation)


必要なら、あなたの Dockerfile(Node/TS用)とセットで「最速になる並び(COPY順/依存/ビルド)」も、この章の流れに合わせて“キャッシュが最大限効く形”へ整形するよ〜🧑‍🔧🔥