WSL2 + Docker Desktop環境のディスク容量逼迫を解決する
docker 10 min read

WSL2 + Docker Desktop環境のディスク容量逼迫を解決する

avatar-m-1

karrinn

著者

Dockerでpytestを実行したら、「OOM Killed (Exit code 137)」でクラッシュ
Windowsのタスクマネージャーを見ると、メモリ35/40GB(90%)。
調査の結果、170GB以上のDockerキャッシュとボリュームが原因でした。今回は、問題の発見から解決まで、実際の手順を振り返ります。

KEY TAKEAWAYS

この記事でわかること

  • docker system dfで問題を特定する方法
  • buildxキャッシュと孤立ボリュームの削除手順
  • 170GB以上を回収した具体的なコマンド

用語の定義

TERM 01

buildxキャッシュ

Docker buildxが蓄積するビルドキャッシュ。イメージビルドの中間レイヤーを保存し、次回ビルドを高速化するが、気づかないうちに数十GB〜数百GBになることがある。

TERM 02

孤立ボリューム (Dangling Volume)

どのコンテナにもアタッチされていないボリューム(LINKS=0)。過去のプロジェクトやコンテナ削除時に残された残骸で、手動削除が必要。

TERM 03

docker system df

Docker全体のディスク使用量を表示するコマンド。Images・Containers・Volumes・Build Cacheの使用量と回収可能サイズを一覧表示。

TERM 04

OOM Killed (Exit code 137)

Out of Memory Killedの略。コンテナがメモリ制限を超えた際、Linuxカーネルがプロセスを強制終了させるエラー。Exit code 137で検出できる。

問題の発見

ある日、docker execでpytestを実行したら、「OOM Killed (Exit code 137)」でクラッシュしました。

Windowsのタスクマネージャーを見ると、メモリ35/40GB(90%)。開発環境全体が重い。

症状1

pytestがOOM Killedでクラッシュ(Exit code 137)

症状2

Windowsタスクマネージャーでメモリ35/40GB(90%)

症状3

開発環境全体が重く、動作が不安定

初期調査: WSL内メモリは問題なし

まず、WSL内のメモリ状況を確認しました。

WSL内は問題なさそう。次にDockerコンテナのメモリ使用状況を確認。

すべて制限内。では、ディスク使用量は?

Bash
free -h
Output
               total        used        free      shared  buff/cache   available
Mem:            19Gi       3.9Gi       253Mi        39Mi        15Gi        14Gi
Bash
docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}"
Output
NAME              MEM USAGE / LIMIT     MEM %
opensearch-dev    1.005GiB / 2GiB       50.26%
django-dev        360.2MiB / 768MiB     46.91%
celery-dev        202.3MiB / 768MiB     26.35%

調査のポイント: メモリもコンテナも問題なし → ディスク使用量を疑う

次にdocker system dfで全体像を確認します。

原因の特定

docker system df で全体像を把握

全体像の把握

Docker全体のディスク使用量を確認しました。

178GBのボリューム! うち82GBが回収可能。
でも、Build Cache 0Bという表示が怪しい。

詳細調査

-vオプションで詳細を表示し、サイズ順にソート。

Bash
docker system df
Output
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          13        11        51.05GB   50.48GB (98%)
Containers      11        11        174MB     0B (0%)
Local Volumes   99        10        178.1GB   82.56GB (46%)
Build Cache     0         0         0B        0B
Bash
docker system df -v 2>&1 | grep -E "^[a-z0-9_-]+\s+[0-9]" | sort -k3 -h -r | head -20
Output (抜粋)
buildx_buildkit_magical_swanson0_state   1   87.05GB   ← buildxキャッシュ!
eedf0548302da03e643cd3c33f1ef26e539cb...  0   7.18GB    ← 孤立ボリューム
cfff1f0ef8682912e40c30710c4bf30e9bfbc...  0   7.18GB
7e0a12ebae9d78b0005dbadc03715603a0610...  0   7.046GB

問題の正体

  • buildxビルドキャッシュ: 数十GB〜(過去のDockerイメージビルドの中間レイヤー)
  • 孤立ボリューム: LINKS=0の未使用ボリューム(古いプロジェクトの残骸)
  • 未使用イメージ: 実行中のコンテナで使われていないイメージ

解決手順

原因が分かったので、順番に削除していきます。一番効果が大きいのはbuildxキャッシュです。

手順1: 孤立ボリュームの削除

意図

コンテナにアタッチされていないボリュームを削除。

結果

数GB程度を回収。次は未使用イメージ。

Bash
docker volume prune -f
Output
Deleted Volumes:
64c7f7bc4b3d9e7e6fcb0ccdae17184975a5e3ebb6395e4b7ce82d23d0fc1c14
...
Total reclaimed space: 1.776GB

手順2: 未使用イメージの削除

意図

実行中のコンテナで使用されていないイメージを削除。

結果

環境により数百MB〜数GB。次はbuildxキャッシュ(ここが本命)。

Bash
docker image prune -a -f
Output
Deleted Images:
untagged: redis:7-alpine
untagged: postgres:16
untagged: alpine:latest
Total reclaimed space: 130.4MB

手順3: buildxビルドキャッシュの削除(最重要)

意図

Docker buildxが蓄積したビルドキャッシュを全削除。最大の効果

重要ポイント

docker system dfではBuild Cache 0Bと表示されても、実際にはボリューム扱いで数十GB〜数百GBになっていることがある。

Bash
docker buildx prune -a -f
Output
Total: 94.61GB

最大の効果

環境によっては数十GB〜100GB以上を回収できる場合があります。これが最も効果的なクリーンアップ手段です。

手順4: 未使用ボリュームの詳細削除

意図

LINKS=0(どのコンテナにも紐づいていない)のボリュームを削除。

注意

重要なデータが残っていないか、事前に確認してください。古いプロジェクトの残骸などを一括削除します。

Bash
docker system df -v 2>&1 | grep -E "^[a-f0-9]{64}\s+0\s+" | awk '{print $1}' | xargs docker volume rm

補足: 環境によっては数十個〜数百個のボリュームが削除される場合があります。

結果

Before / After比較

項目Before(例)After(例)回収量(例)
ボリューム178GB (99個)15GB (22個)163GB
buildxキャッシュ94.6GB0B94.6GB
イメージ51GB50.5GB0.5GB

効果

環境により数十GB〜100GB以上を回収可能。pytestなどのメモリ不足エラーも解消され、開発環境全体が軽快に。

今後の予防策

一度クリーンアップしても、また溜まるので、定期的なメンテナンスが重要です。

定期的なクリーンアップ

推奨頻度

月1回など、定期的に以下のコマンドを実行します。

注意

docker system prune -a --volumes -fは、使用中でないすべてのリソースを削除します。重要なデータが残っていないか、事前に確認してください。

Bash
# 全部まとめて削除(注意: 使用中でないものすべてが対象)
docker system prune -a --volumes -f
docker buildx prune -a -f

docker-composeでのボリューム管理

効果

docker-compose down -vを使うと、関連ボリュームも一緒に削除されます。

注意

データベースのボリュームも消えるので、開発データを残したい場合は-vオプションなしで実行してください。

Bash
# コンテナとボリュームを一緒に削除
docker-compose down -v

WSLメモリ制限の設定

設定方法

~/.wslconfigで明示的にメモリ上限を設定できます。

配置場所

Windowsのホームディレクトリ(C:\Users\<username>\.wslconfig)に配置し、WSLを再起動すると有効になります。

~/.wslconfig
[wsl2]
memory=16GB
swap=8GB

まとめ

  • Docker Desktop + WSL2環境では、buildxキャッシュと孤立ボリュームが蓄積しやすい
  • docker system df -vで詳細なディスク使用量を確認できる
  • docker buildx prune -a -fが最も効果的な場合が多い(今回は94.6GB回収)
  • 定期的なクリーンアップを習慣化することが重要

教訓

Docker環境は気づかないうちに肥大化します。
定期的にdocker system dfで確認し、docker buildx prune -a -fでクリーンアップする習慣をつけましょう。

参考コマンド一覧

コマンド用途
docker system dfDocker全体のディスク使用量を表示
docker system df -v詳細(各イメージ・ボリュームごと)を表示
docker volume prune -f孤立ボリュームを削除
docker image prune -a -f未使用イメージを削除
docker buildx prune -a -fbuildxキャッシュを削除(最重要)
docker system prune -a --volumes -f上記すべてをまとめて実行
free -hシステムメモリ使用量を確認(WSL内)
docker stats --no-streamコンテナごとのリソース使用量を確認

参考リンク

公式ドキュメント

関連記事

関連トピック

コメント (0)

まだコメントはありません。最初のコメントを残しませんか?

コメントを投稿

メールアドレスが公開されることはありません。必須項目には * が付いています