Docker開発でのディスク肥大化を防ぐ。安全なクリーンアップ手順と運用の工夫
目次
開閉
複数のプロジェクトを並行して動かしていたり、日常的にコンテナのビルドや検証を繰り返していると、ある日突然OSから「ストレージの空き容量が少なくなっています」と警告されてぎょっとすることがあります。
ディスクの使用内訳を調べてみると、Dockerの仮想ディスクファイル(MacのDocker Desktop仮想ディスクやWindowsのWSL2仮想ディスク)が50GB、場合によっては100GB以上も消費していた、というのは現場でも珍しくない光景です。
「作業が終わったコンテナはこまめに止めているし、不要になった古いプロジェクトはディレクトリごと削除したはずなのに、なぜこんなに容量が膨らむのか」
今回は、Dockerがディスクを食いつぶす本当の理由を整理したうえで、大切な開発データを誤って吹き飛ばさずに、ギガ単位の空き容量を安全に取り戻す実践的なクリーンアップ手順をお話しします。
まず結論:今すぐ安全に空き容量を取り戻す手順
急ぎでストレージを空けたい方向けに、まずは「手元の開発データを失うリスクが極めて低く、かつ効果が高い最短コマンド」から提示します。
1. まず現在の消費状況を確認する
闇雲に消す前に、何がどれだけ容量を占有しているのかを把握します。
docker system df
このコマンドを実行すると、以下のようにコンテナ、イメージ、ボリューム、ビルドキャッシュごとの使用量と、削除可能な容量(RECLAIMABLE)が一目で分かります。
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 18 4 12.4GB 8.1GB (65%)
Containers 6 2 142MB 58MB (40%)
Local Volumes 15 3 4.2GB 1.8GB (42%)
Build Cache 142 0 38.6GB 38.6GB (100%)
多くの場合、一番右の RECLAIMABLE(回収可能容量)で圧倒的なサイズを叩き出しているのは「Build Cache」と「Images」です。
2. 安全に一括クリーンアップを実行する
状況を確認したら、以下のコマンドを実行します。
docker system prune
実行すると「停止中のコンテナ」「使われていないネットワーク」「タグなし(dangling)イメージ」「使われていないビルドキャッシュ」が一括で削除されます。
確認プロンプト(Are you sure you want to continue? [y/N])が出るので、y を入力してエンターを押せば完了です。これだけで、日常的に溜まった十数GB〜数十GBのゴミが安全に回収されます。
なぜDockerはここまで肥大化するのか?
こまめにコンテナを停止していてもディスクが圧迫される背景には、Dockerが開発スピードを優先するために採用しているキャッシュ機構と中間生成物の存在があります。
1. BuildKitの「ビルドキャッシュ」が蓄積し続ける
近年のDockerビルド(BuildKit)は非常に賢く、2回目以降のビルドを高速化するためにレイヤーごとのキャッシュを積極的にディスクへ残します。
マルチステージビルドを多用したり、ベースイメージの更新やパッケージのインストール手順を頻繁に変更していると、過去の古いビルドキャッシュが破棄されずにそのままディスクに残り続けます。先ほどの docker system df で Build Cache が数十GBに膨れ上がっていたのは、これが主な原因です。
ビルドキャッシュだけを明示的にクリアしたい場合は、以下のコマンドが使えます。
# 使われていないビルドキャッシュを全削除
docker builder prune2. タグを失った「Danglingイメージ(<none>)」
同じ名前のイメージを新しくビルドしたり docker pull で最新版を取得すると、これまで使われていた古いイメージはタグを奪われ、<none>:<none> という名無しのイメージ(Danglingイメージ)に変化します。
これらは現在動いているコンテナから参照されていない限り、単なる過去の遺物としてディスク領域を占有し続けます。
3. 名前を持たない「Anonymous Volumes」の残留
docker-compose down などを実行した際、明示的に名前を付けていない無名ボリューム(匿名ボリューム)が残り続けるケースがあります。これらは docker compose down -v と明示しない限り自動では消えないため、長期間の開発の中でじわじわと溜まっていきます。
やってはいけない!事故を防ぐ安全運用の鉄則
容量を取り戻したい一心で、Web上のコマンドをよく確認せずにコピペ実行すると、取り返しのつかない現場トラブルに直結することがあります。特に注意すべき2つのポイントを押さえておきましょう。
1. 安易に --volumes を付けない
docker system prune には、ボリュームまで一括削除するオプション(--volumes)が存在します。
# 【危険】コンテナに接続されていないボリュームをすべて削除してしまう
docker system prune --volumes
これを実行すると、現在停止しているコンテナに紐づいているボリュームも含め、使われていないボリュームがすべて吹き飛びます。
例えば、ローカル開発用のPostgreSQLやMySQLで「DockerボリュームにDBデータを永続化していた」場合、コンテナが停止している状態でこのコマンドを叩くと、丹念に投入したテストデータやマイグレーション済みのデータが跡形もなく消去されます。
ボリュームの整理は、個別に中身を確認しながら docker volume ls や docker volume rm <ボリューム名> で行うか、不要になったプロジェクトの作業完了時に docker compose down -v で個別に明示して消すのが最も安全です。
2. -a(--all)オプションの使い分け
docker system prune -a を指定すると、タグなしイメージだけでなく「現在稼働中のコンテナから参照されていないすべてのイメージ」が根こそぎ削除されます。
空き容量は劇的に回復しますが、次に別プロジェクトを起動する際、ベースイメージ(Node.jsやGo、Pythonなど)のダウンロードやビルドが最初からやり直しになるため、膨大なダウンロード時間と通信が発生します。
通常のお掃除では -a は付けず、標準の docker system prune で十分な効果が得られます。どうしてもディスクが限界に近いときだけ、再取得に時間がかかることを承知のうえで実行するようにしましょう。
習慣化:ディスク容量を平和に保つ工夫
都度手動でコマンドを思い出すのは負担になるため、私は以下のような形で日常のワークフローに組み込んでいます。
1. シェルに関数またはエイリアスを定義しておく
zshやbashの ~/.zshrc(またはPowerShellの $PROFILE)に、安全なクリーンアップコマンドを短い名前で登録しておきます。
# 安全なDockerクリーンアップ用エイリアス
alias dclean='docker system prune && docker builder prune -f'
週末の作業終わりや、新しい大きめのプロジェクトをクローンする前のタイミングで dclean をポンと叩くだけで、常に手元を清潔に保つことができます。
2. BuildKitの自動ガベージコレクション(GC)を設定する
毎回手動でキャッシュを消すのが面倒な場合は、Dockerデーモン側の設定でキャッシュの保持上限を設定しておくのも効果的です。
Docker Desktopの設定画面(Settings → Docker Engine)または /etc/docker/daemon.json に、以下のようにキャッシュ上限(例: 20GB)を記述できます。
{
"builder": {
"gc": {
"enabled": true,
"defaultKeepStorage": "20GB"
}
}
}
この設定を入れておくと、ビルドキャッシュが指定した容量を超えた際に、古いものから自動的に破棄されるようになります。
OS別の注意点:ファイルを消してもホストの容量が戻らない問題
Dockerのクリーンアップコマンドを実行してコンテナ内では容量が空いたように見えても、MacやWindowsのホストOS側の空き容量が1バイトも増えていないことがあります。
これは、Docker DesktopがホストOS上に「可変サイズの仮想ディスクファイル(.raw や .vhdx)」を確保しており、中身のファイルを削除しても仮想ディスク自体のサイズが自動で縮小されない場合があるためです。
- Mac(Docker Desktop)の場合:
Settings→Resources→Virtual disk limit周辺で定期的にトリム(Trim)が自動実行されますが、手動で即座に反映させたい場合は、Docker Desktopの設定画面の虫眼鏡/トラブルシューティングアイコンから「Clean / Purge data」を適切に選ぶか、一度Docker Desktopを再起動すると容量が返却されることがあります。 - Windows(WSL2 / Docker Desktop)の場合:
WSL2のバックエンド仮想ディスク(
ext4.vhdx)は、内部でファイルを削除しても自動的には縮小されません。最近のWSL2では.wslconfigにautoMemoryReclaim=dropcacheや sparse VHD の設定を入れることで自動回収されるようになっていますが、古い環境ではPowerShellからwsl --manage <ディストリビューション> --set-sparse trueを設定するか、diskpartでvhdxをコンパクト化する必要があります。
「コマンドを叩いたのにホストのストレージが増えない」という時は、Docker内のデータだけでなく仮想ディスクファイル自体の挙動を疑ってみてください。
まとめ:環境の定期メンテナンスを味方につける
Dockerは現代の開発現場において欠かせない強力な基盤ですが、仕組み上どうしても中間データやキャッシュが裏側に蓄積しやすいツールでもあります。
- 普段のメンテナンスは
docker system dfで把握し、docker system pruneで安全に回収する。 - ローカルDBの消失を防ぐため、
--volumesや-aは意図とリスクを理解した時だけ使う。 - キャッシュ上限(GC)の設定やエイリアスを活用し、無理のないペースで自動化・習慣化する。
快適な開発環境を保つために、ぜひご自身の手元の環境でも一度 docker system df を叩いて、どれだけの「眠れる容量」があるか確かめてみてください。