GitHub Actions Docker ビルドのログなし cancel と swap 削除メモ
概要
GitHub Actions の Docker ビルドで、エラー本体が出ないままログ更新が止まり、最終的に The operation was canceled. で終わる事象に遭遇した。
観測した状況は次の通り。
-
df -hではディスク空き容量が残っていた - ディスク確保用に
jlumbroso/free-disk-spaceを入れていた -
swap-storage: trueにより、有効な swap があれば無効化される状態だった - swap を削除しない設定を含む変更でビルドが完走した
状況情報から、メモリと swap 容量が関与した次の経路を主な原因候補とした。
前提
- 対象: GitHub-hosted Ubuntu runner 上の Docker BuildKit ビルド
- ビルド対象: Node.js 系フロントエンドアプリ
- 利用 Action:
jlumbroso/free-disk-space@v1.3.1
jlumbroso/free-disk-space@v1.3.1 は、GitHub-hosted runner 上の事前導入ツールや Docker images、swap などを削除対象として選べるサードパーティ Action。ディスク空き容量を増やす目的で使用。
ディスク不足とメモリ不足
- ディスク: Docker image、cache、一時ファイルなどを保存する場所。足りないと
No space left on deviceになる。 - メモリ: ビルド中のプロセスが使う作業領域。足りないと OOM kill の候補になる。
- swap: メモリが足りないときに、ディスクの一部を一時的な退避先として使う仕組み。swap がない場合は退避先がなく、プロセス終了につながりやすくなる。
発生した事象
観測できたことと、当時の条件は次の通り。
- ビルド開始後、BuildKit のログが特定ステージで止まる
- その後、エラー本体が出ないまま一定時間後に cancel 扱いになる
-
df -hではディスク空き容量が残っている - 直近で依存追加があり、ビルド時のメモリ使用量が増えている可能性があった
ログ上は次のように見える。
... (Step: Build)
... (BuildKit のログが特定ステージで途切れる)
##[error] The operation was canceled.
free-disk-space を入れていた理由
対象のワークフローでは、以前から Docker ビルド時のディスク枯渇を避けるために jlumbroso/free-disk-space を使っていた。
- GitHub-hosted runner には Android SDK、.NET、Haskell、tool cache などが事前導入されている
- Docker build / BuildKit は、イメージビルドや cache import/export の過程で runner のディスクを使う
- ビルド内容やキャッシュ設定によっては、ジョブ途中で
No space left on deviceになる
そのため、Docker Buildx を起動する前に不要な事前導入ツールを削除し、ビルドで使えるディスク空き容量を増やしていた。今回の原因候補は、この cleanup の対象に swap も含まれていた点だった。
swap-storage の挙動
action.yml では、swap-storage の default は true。この入力が true のとき、内部で次の処理が実行される。
sudo swapoff -a || true
sudo rm -f /mnt/swapfile || true
free -h
-
有効な swap を
swapoff -aで無効化し、この Action が削除対象にしている/mnt/swapfileを削除する。 -
ディスク不足への対処としては有効でも、メモリピークが大きいビルドでは、swap を無効化することで別の失敗要因になりうる。
OOM kill とログ
-
Linux では、メモリが足りなくなるとカーネルがプロセスを選んで終了させることがある。この仕組みが OOM killer。
-
OOM killer は選んだプロセスに
SIGKILLを送る。SIGKILLはプロセス側で捕捉できないため、通常終了時の後処理やログ出力を最後まで実行できない場合がある。 -
BuildKit 本体または配下のビルドプロセスが OOM kill された場合、最後のエラーが Actions ログに残らないことがある。ただし、Actions の cancel / timeout 表示だけで OOM kill とは断定できない。
修正
swap を削除しないように swap-storage: false を明示した。
- name: Free disk space
uses: jlumbroso/free-disk-space@v1.3.1
with:
tool-cache: true
android: true
dotnet: true
haskell: true
large-packages: false
docker-images: false
swap-storage: false
設定ごとの影響は次のようになる。
-
swap-storage: true: swap ファイル分のディスク空き容量が増える。一方で、メモリ不足時に swap を使えなくなる。 -
swap-storage: false: swap は維持される。一方で、swap ファイル分のディスク空き容量は増えない。
この Action を使う目的が No space left on device の回避なら、swap まで削る必要があるかを分けて考える。
まとめ
-
df -hでディスク空き容量が残っていても、エラー本体が出ない停止は OOM kill の可能性がある -
jlumbroso/free-disk-space@v1.3.1はswap-storageの default がtrue - ディスク枯渇対策の cleanup が、メモリ不足時の失敗要因候補になることがある