dockerのディスク容量削減

dockerは多彩な開発環境がそれぞれパッケージ化されていて便利なのですが、継続的に使っていくうちに過去のコンテナ関連ファイルがあふれてディスク容量を圧迫していきます。

とくに、MacOSなどの環境では、Macの中にLinuxの環境が作られる構成となり、Linux用のファイルシステムを使い切るとコンテナが起動しなくなります。

“No space left on device”のバリエーション

コンテナが起動しないケースで、docker logs _some_container_name_を実行して、”No space left on device”のようなエラーが出力されている場合は、ディスク領域が枯渇しています。また、docker-composeでまとめて起動した際に同時多発で異常終了する症状も特徴的です。

そのほか、イメージビルド中に”No space left on device”エラーに遭遇したケースでは、単に中間ビルドイメージが破損していたケースもありました。

このケースではディスク容量が枯渇していないことを確認したうえで、docker image rmコマンドで破損イメージを削除→再ビルドしたら直りました。

docker system pruneで一括削除

過去のコンテナ(稼働中のコンテナ以外)の関連ファイルを一括で削除したい場合には、 docker system pruneコマンドを使えます。

docker system pruneはいくつかのサブコマンドを連続実行し、以下のように一括でスペース解放できます。

$ docker system prune
WARNING! This will remove:
	- all stopped containers
	- all volumes not used by at least one container
	- all networks not used by at least one container
	- all dangling images
Are you sure you want to continue? [y/N] y

...

Total reclaimed space: 672.7MB

ディスク領域を消費するファイルの種類は、主に以下の3系統があります。

  • コンテナのイメージファイル。それぞれ数百MB程度のものが多い。また、旧バージョンのイメージなども残る。docker imagesで確認できる
  • 起動時にVOLUME指定したディレクトリ上のファイル。データベースなどの場合は、データがここに書き込まれて容量を消費していく。docker volume lsでリスト表示される
  • 非VOLUMEのコンテナ内ファイルシステムの変更(コンテナそのもの)。

-aオプションで強力削除

docker image pruneはタグのついていない(dangling)イメージを削除するため、常用には十分な挙動と言えます。

docker system prune -aまたはdocker image prune -aのようにaオプションをつけるとさらにアグレッシブに削除する挙動となり、現在使用しているコンテナインスタンスから参照されていないものをすべて削除します。

WARNING! This will remove all images without at least one container associated to them.
Are you sure you want to continue? [y/N] y

...

Total reclaimed space: 5.058GB

実験的に様々なイメージをためしていて、一度削除したい、というような用途で使えるでしょう。

古いdocker用の代替コマンド

docker v1.13(2016年秋)以降は各種サブコマンドにpruneが実装されていますが、それ以前の古い実行環境の場合は以下のようなシェルスクリプトで代用できます。

過去のイメージでタグのついていないイメージを一括削除したい場合には、以下のようなワンライナーをシェルのaliasに登録して利用しています。

docker rmi $(docker images | awk '/^<none>/ { print $3 }')

なおnoneのイメージを削除すると、以下のようなエラーに頻繁に遭遇します。

Error response from daemon: conflict: unable to delete f34642d9a60b (must be forced) - image is being used by stopped container 7fc4bcc69dd0

これは、イメージを利用中のコンテナが存在していることを示していて、コンテナを削除することでイメージを消せるようになります。

上の例では、docker ps -a | grep 7fcのようなコマンドで、該当コンテナが何なのかを探せます。

多くのケースでは、docker buildの途中で異常終了した際の残骸などがこのような形で残っています。コンテナを消しても問題ないことが確認できたら、docker rm 7fcのように削除できます。

VOLUMEはdocker volume rmコマンドで削除できます。

danglingステータスのVOLUMEを一括削除するために、以下のようなワンライナーをalias登録して利用しています。

docker volume rm $(docker volume ls -qf dangling=true)

VOLUMEはリストを見てもどのようなデータが入っているのか分からないため、ディスクスペースの運用の観点からはここに重要なデータが置かれないように配慮した方が良いでしょう。

aufsよりも書き込みが速いことからRDBMSなどのイメージではDockerfileにVOLUMEがあらかじめ設定されているケースも多いので、不用意に重要なデータが置きざりになる懸念があります。

このように、現状ではdockerを利用していると過去の残骸が蓄積しがちであるため、たまにクリーンアップが必要になります。

中馬崇尋
Chuma Takahiro