docker『No Space Left on Device』の原因と対処法

docker『No Space Left on Device』の原因と対処法

ディスクの空き容量(バイト)またはiノード数が枯渇すると、イメージpull/ビルド/コンテナ起動/ログ書込みが失敗する。まず「どのパーティション・どのリソース(容量 or iノード or Docker専用領域)」が詰まっているかを特定し、不要アーティファクト削除・ログ圧縮・ビルドキャッシュの破棄・データルート移設・ディスク拡張の順で解消する。

症状と発生条件(まず把握)

・docker build / pull / run / load / save / compose up 等で「no space left on device」が発生。

・/var/lib/docker 配下(overlay2/containers/volumes など)が肥大化、あるいは/var やルートパーティションが満杯。

・iノード枯渇(小ファイル大量)でも同じエラーが出る。KubernetesノードやCI環境で特に起きやすい。

クイック診断(どこが詰まっているかを即確認)

# 1) パーティションの空き容量とiノード
df -h
df -i

# 2) Dockerが使っているディスク量(BuildKit含む)
docker system df -v

# 3) どのディレクトリが重いか(ルート直下→Docker直下)
sudo du -xh --max-depth=1 / | sort -h | tail -n 10
sudo du -xh --max-depth=1 /var/lib/docker | sort -h | tail -n 20

# 4) 大きいログファイルの探索(JSONログ等)
sudo find /var/lib/docker/containers -name "*-json.log" -size +100M -printf "%p %k KB\n" | sort -nk2 | tail

不要なコンテナ/イメージ/ネットワーク/ビルドキャッシュを削除

# 停止コンテナ・未使用ネットワーク・ダングリングイメージ・未参照ビルドキャッシュを削除(安全寄り)
docker system prune -f

# さらに未使用イメージ/ボリュームも対象(影響が大きい。必ず影響範囲を確認)
docker system prune -a -f --volumes

# BuildKit/ビルドキャッシュを個別に掃除
docker builder prune -f
docker builder prune -a -f      # すべてのキャッシュ(再ビルドが重くなる)

ボリュームと匿名ボリュームの掃除(占有が大きい場合)

# 利用状況の確認
docker volume ls
docker system df --volumes

# 使っていないボリュームを削除(慎重に)
docker volume prune -f

# どのボリュームが重いか確認
sudo du -xh /var/lib/docker/volumes | sort -h | tail -n 20

ログ肥大の抑制と即時圧縮(json-fileドライバの対策)

# 直近の巨大ログのサイズ確認
sudo du -h /var/lib/docker/containers/*/*-json.log | sort -h | tail

# 一時的対処:サイズを削る(稼働中サービスならまずローテーション設定を適用すること)
: > /var/lib/docker/containers/<CONTAINER_ID>/<CONTAINER_ID>-json.log


# 永続的対策:/etc/docker/daemon.json でログローテーション
# 反映にはDockerデーモン再起動が必要(既存コンテナは再作成推奨)
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
# 反映
sudo systemctl daemon-reload && sudo systemctl restart docker

iノード枯渇の対処(容量はあるのにエラーが出る場合)

# iノード使用率を確認
df -i

# 小ファイルの大量生成源を特定(例:一時ファイル、キャッシュ、レイヤ断片)
sudo find /var/lib/docker -xdev -type f | wc -l
sudo find /var/tmp -xdev -type f -printf "%T+ %p\n" | sort | tail -n 50

# 不要ファイル/キャッシュを削除(prune等)後に再確認
docker system prune -a -f --volumes
df -i

・根本的にはファイルシステムの再作成(inode密度増)や、ディレクトリ分割・別パーティション化で恒久対策。

データルートの移設・ディスク拡張(/var が恒常的に不足する)

# 1) Docker停止
sudo systemctl stop docker

# 2) 新しいディスク/パスを用意し空ディレクトリ作成(例:/mnt/docker)
sudo mkdir -p /mnt/docker
sudo rsync -aHAX --delete /var/lib/docker/ /mnt/docker/

# 3) /etc/docker/daemon.json に data-root を指定
{
  "data-root": "/mnt/docker"
}

# 4) 再起動して確認
sudo systemctl start docker
docker info | grep "Docker Root Dir"

・クラウド/VMならディスク拡張→ファイルシステム拡張(LVM/EXT4/XFS)も選択肢。

Docker Desktop / WSL2 / macOS / Windows の専用対策

# Docker Desktop(macOS/Windows):GUI → Settings → Resources → "Clean / Purge data"
# CLIでもおおむね同様
docker system prune -a -f --volumes

# WSL2:VHDXの肥大を縮小(Windows PowerShell 管理者)
wsl --shutdown
Optimize-VHD -Path "$env:USERPROFILE\AppData\Local\Docker\wsl\data\ext4.vhdx" -Mode Full

・WSL2ディストリごとに大容量のイメージ/ボリュームが残っていないか確認。

・Docker Desktopの「Disk image size」「Prune images/volumes」を定期的に実施。

KubernetesノードでのBackOff/ENOSPC対処(containerd/CRI-O)

# イメージとコンテナのGC状況
crictl images
crictl ps -a

# 不要イメージの削除(要注意:稼働中のPodに影響しないように)
crictl rmi --prune

# containerd の空き容量・ミラー設定を見直し(必要に応じて)
sudo systemctl restart containerd

・ノードのログ(/var/log/containers, /var/log/pods)・監査ログの肥大化も要確認。

・kubeletの–image-gc-high-threshold/low-threshold 設定で自動GCを強化。

CI/CDやビルドでのキャッシュ・レイヤ設計(再発防止)

# .dockerignoreで不要ファイルを送らない(レイヤ膨張防止)
node_modules
.git
tmp
logs
[/code]
[code]
# ビルドキャッシュの明示的な掃除(定期ジョブなど)
docker builder prune -af
docker image prune -af
docker volume prune -f

・マルチステージビルドで最終イメージを最小化。

・apt/yumキャッシュは同一RUN内で削除(レイヤ肥大を避ける)。

ジャーナル/システムログの整理(/varが詰まる典型)

# systemdジャーナルを容量基準で掃除(例:200M残し)
sudo journalctl --vacuum-size=200M

# 期間指定(例:7日より古いものを削除)
sudo journalctl --vacuum-time=7d

NG→OK早見(クイック修正)

・NG:原因特定前に闇雲に削除 → OK:df/df -i/docker system df/duで「どこが詰まりか」を特定。

・NG:jsonログを放置 → OK:daemon.jsonでmax-size/max-fileを設定しローテーション。

・NG:latest多用で頻繁pull → OK:タグ/ダイジェスト固定とキャッシュ再利用。

・NG:/var固定運用 → OK:data-root移設やディスク拡張。

・NG:CIで毎回巨大キャッシュ生成 → OK:.dockerignore/マルチステージ/定期prune。

・NG:容量はあるがエラー → OK:df -iでiノード枯渇を確認して小ファイルを整理。

チェックリスト(上から順に潰す)

・df -h / df -i / docker system df の結果を保存して原因を切り分けたか。

・prune(system/builder/volume)とログローテーション設定を実施したか。

・大容量ディレクトリと巨大ログを特定し、恒久対策(設定/設計)を入れたか。

・必要ならdata-root移設またはディスク拡張を行ったか。

・Desktop/WSL2/K8sなど実行環境固有の掃除/最適化を適用したか。

・再発防止のため、CI/CD・ビルド設計・監視(容量/ファイル数)を整備したか。