はじめに
GitHub Actions の Docker ビルドが No space left on device で落ちた。原因の切り分けとディスク容量を確保した対応をまとめる。
全体
build-push-action は GitHub Actions 側の入口、buildx は Docker CLI 側の実行口、BuildKit は実際にビルドするエンジン。
発生した事象
フロントエンドアプリの Dockerfile を docker buildx build でビルドする途中、外部キャッシュへの書き出し段でエラーが発生した。
ERROR: failed to solve: failed to prepare ...: write ...: no space left on device
ワークフローは GitHub-hosted runner 上で以下の構成。
-
docker/setup-buildx-actionで buildx 起動 -
docker/build-push-actionで外部キャッシュバックエンドへのcache-toを指定 -
cache-toのmodeはmax - 対象イメージは Node.js 系フロントエンドアプリ(
node_modules・ビルド成果物を含むマルチステージビルド)
df -h をジョブ内に挟んで確認すると、cache export の直前に空き容量がほぼ尽きていた。レイヤー単位の詳細な内訳までは追っていないが、ビルド中の一時ファイルと cache export がディスクを圧迫していたように見受けられた。
Linux runner のディスク容量
標準 Linux ランナーの SSD storage は 14 GB とされている。
GitHub-hosted runner image には多くのツールが事前導入されている。Docker ビルドで実際に使える空き容量は、この数字より小さい前提で見る。
BuildKit の mode=max の性質
mode パラメータは次の挙動になる。
| mode | キャッシュ対象 | ディスク面の見方 |
|---|---|---|
min |
結果イメージにエクスポートされるレイヤーのみ | 対象が絞られる |
max |
中間ステップを含む、すべてのレイヤー | 対象が広がり、キャッシュが大きくなりやすい |
mode=max はキャッシュヒット率を上げやすい一方、mode=min より export 対象のキャッシュが大きくなりやすく、import/export 時間やストレージ使用量が増える場合がある。今回のログと df -h の推移からは、cache export 周辺でローカルディスクが枯渇したと思われる。
暫定対処: jlumbroso/free-disk-space で容量確保
-
jlumbroso/free-disk-spaceは、GitHub-hosted runner に事前導入されている Android SDK、.NET、tool cache、swap などを削除して空き容量を作る サードバーティ GitHub Action。 -
GitHub 公式の Action ではないため、信頼性は自分で確認して扱うこと。今回は公開リポジトリでソースを確認できること、MIT License で公開されていること、Release が作成されていることなどを確認したうえで、実行内容を固定するために full-length commit SHA で指定した。
-
Set up Docker Buildxの直前に以下を追加した。
- name: Free disk space
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: false
docker-images: false
swap-storage: true
README 記載の解放量目安(全オプション有効時)は以下。
| 対象 | 解放量 |
|---|---|
| Android | ~14 GiB |
| Tool cache | ~5.9 GiB |
| Large packages | ~5.3 GiB |
| Swap storage | ~4.0 GiB |
| .NET | ~2.7 GiB |
| Haskell | 0 B |
| 合計(全オプション有効時) | ~31 GiB |
※ この表は README 上の目安であり、今回設定の実測ではない。実際の解放量は runner image の内容に左右されるので、必要なら df -h を前後に入れて確認する。