「DockerのNo space left on deviceが解決しない」のでふわっと調べてみた。

こんにちは:sunny:

株式会社HRBrainでバックエンドエンジニア（とフロントエンドエンジニア？）をしているみつです！

DockerをBuildしようとする際に、`No space left on device`に時々出会います。

これまでは**Dockerを掃除するコマンド**を実行すれば元に戻ってきたのですが、今回サクッと解決できない事象にぶつかったので**別の方法で解決をした**、記事です。

:::note warn
確認した環境は、Docker for Macだけです。
WindownsやLinuxでは起きない事象の可能性があります。

**ローカル環境のバージョン**
- Mac OS: Monterey 12.6.4
- Docker: Docker version 27.2.0
- Docker Desktop: 4.34.3（と4.35も最後に確認）
:::


## 何が起きたか
Dockerを立ち上げようとした際に下記のエラーに遭遇しました。

```sh
Build Failed: ...: no space left on device
```

これまでは、
- `docker image prune -a`
- `docker system prune`
- `docker volume prune`

を実行することで未使用のイメージ等を消すことで容量を確保し、解決ができていました。

しかし、今回上記を実行しても`no space left on device`エラーが解消しませんでした。

## 解決した方法

> 最大サイズを減らした場合、現在のディスクイメージファイルは削除されます。つまり、すべてのコンテナとイメージは消滅します。

Docker公式ドキュメント（日本語）にこのように書かれていたので、Virtual disk limitを無理やり下げ、残っているファイルを削除しました。

「**Virtual disk limitで設定されている容量を下げて、Apply & Restart**」

少し強行突破感もあります。

もし他の解決の方法があればぜひ教えてください。笑

[1]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841912/74d46720-07c7-94fb-04d3-8f3a09515fda.png)

[2]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841912/55350524-212a-8ba4-9d88-efed8c3b9a9e.png)


## 掃除コマンドの説明

### `docker image prune -a`

> docker image prune コマンドは、使っていないイメージをクリーンアップできます。デフォルトの docker image prune は、宙ぶらりんイメージ（dangling image）のみ削除します。宙ぶらりんイメージとは、タグを持たず、他のコンテナからも参照されないイメージです。宙ぶらりんイメージを削除するには、次のようにします。

使っていないイメージをクリーンアップするコマンドです。

`-a`をつけることで、タグづけなし、参照なしを問わず、未使用のイメージをすべて削除することができます。

### `docker system prune`

> docker system prune コマンドは、イメージ、コンテナ、ネットワークを削除（prune）するショートカットです。ボリュームはデフォルトでは削除されないため、ボリュームを削除するには docker system prune で --volumes フラグを使う必要があります。

イメージやコンテナ、ネットワークを削除することができるコマンドです。

--volumesフラグを使うことでボリュームを削除することができます。

### `docker volume prune`

> ボリュームは１つもしくは複数のコンテナによって利用されるもので、Docker ホスト上で容量を使います。ボリュームの削除はデータの破棄にあたるため、決して自動的に削除されません。

未使用のボリュームを削除することができるコマンドです。

## その他コマンド等の説明
### `docker system df`

> docker のディスク使用量を表示します。

docker デーモンが使用しているデータの概要を見ることができるコマンドです。

### `du -sm Docker.raw`

> ディスクの使用状況を要約します。

ディスクの使用状況を要約するコマンドです。

`-s`と`-m`はそれぞれ以下の挙動をし、`du -sm Docker.raw`を実行することで`Docker.raw`ファイルが何MBを使用しているかを知ることができます。

#### `-s`オプション
- 指定されたファイルごとにディスク使用率が表示されるオプション
> 指定されたファイルごとに、ファイルのディスク使用率が表示されます。 指定されたディレクトリーごとに、ディレクトリー内 (すべてのサブディレクトリーを含む) のすべてのファイルの合計ディスク使用量が表示されます。 このフラグを、-a フラグと比較してください。

#### `-m`オプション
- MB単位で計算するオプション

> デフォルトの 512 バイト単位ではなく、MB 単位でブロック・カウントを計算します。バイトでの各ユニットの値は非常に高いため、 ディスク使用状況の出力値は、浮動小数点を使用した数になります。


## Docker for Mac におけるディスク

> Docker Desktop で Linux コンテナとイメージを保管するのは、Mac ファイルシステム内の単一の大きな「 ディスク イメージdisk image 」ファイルです。これは Linux 上の Docker が /var/lib/docker ディレクトリにコンテナとイメージを保管するのとは異なります。

Docker for Macにおいてコンテナとイメージを保管するのは、Virtual diskで設定している先に保存をするようです。

:::note info
Virtual diskとは、仮想的に提供される保存領域です。
:::


## 掃除コマンドで削除しきれないものがある？
掃除コマンドを実行後、`docker system df`を実行してみたところ、とても綺麗。

しっかりイメージやコンテナ、ビルドキャッシュは削除されています。

```
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     1         0         0B        0B
```

しかし、「No space left on deviceが解決しない」のでDocker for Macが保存しているDisk image locationを見に行ってみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841912/de3784f6-b298-e318-a1d3-cf49527a2fc7.png)

`cd 上記のDisk image location`で確認すると全部を掃除したはずなのに何かのファイルが残っています。

```shell
...% du -sm Docker.raw                                                       
23413	Docker.raw
```

しかも、**Dockerを起動して、掃除コマンドを繰り返すと何かのファイルが蓄積されていく**ことが判明しました。

別タブでDockerを起動した後、それぞれの掃除コマンドを実行した後の`du -sm`の実行結果は下記の通りです。

```sh
...% docker system df          
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     1         0         0B        0B
 
// MEMO: 別のタブでDockerを起動する
...% du -sm Docker.raw 
56358	Docker.raw

// MEMO: 別のタブでDockerを落として、docker image prune -aする
...% du -sm Docker.raw
53486	Docker.raw

// MEMO: 別のタブでDockerを落として、docker system pruneする
...% du -sm Docker.raw
19120	Docker.raw

// MEMO: 別のタブでDockerを落として、docker volume pruneする
...% du -sm Docker.raw
17815	Docker.raw

...% docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     1         0         0B        0B
```

## 他の方も困ったことがあるかもしれない？

他の方の記事で、下記の様なものを見つけました。

Dockerの公式ドキュメントで明確なそういった記述を見つけることはできなかったですが、`du -sm`で確認しながら進めていたところ、謎ファイルが残ったため、実際に残りかすが溜まる状況もあり得るのかもしれません。

> Docker for Macはイメージをbuildすると残りかすがちょっとづつ溜まっていくので、定期的にdisk imageをお掃除する必要がある。

https://blog.pinkumohikan.com/entry/cleanup-docker-disk-image

## Docker Desktop 4.35がリリース
2024年11月15日時点で新しいバージョンのDocker Desktopがリリースされていたので、更新して確認してみました。

### アップデート後の画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841912/9e8587ee-33ad-e59c-0bf8-8ba110c100e5.png)

### 実行結果
それぞれのコマンド実行後に、`docker system df`で確認しながら容量を確認してみます。

結果的は、**Docker Desktop4.35でも自分の環境では起こる**ようでした。

```sh
// MEMO: DockerをBuild（1回目）
~/data % du -sm Docker.raw 
36344	Docker.raw

// MEMO: Dockerを落とした状態
~/data % du -sm Docker.raw 
36307	Docker.raw
~/data % docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          31        0         27.86GB   27.86GB (100%)
Containers      0         0         0B        0B
Local Volumes   10        0         48.52MB   48.52MB (100%)
Build Cache     295       0         3.928GB   3.928GB

// MEMO: docker image prune -aを実行後
~/data % du -sm Docker.raw
34830	Docker.raw
~/data % docker system df 
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   10        0         48.52MB   48.52MB (100%)
Build Cache     295       0         27.03GB   27.03GB

// MEMO: docker system prune を実行後
~/data % du -sm Docker.raw
12236	Docker.raw
~/data % docker system df 
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   10        0         48.52MB   48.52MB (100%)
Build Cache     1         0         0B        0B

// MEMO: docker volume prune を実行後
~/data % du -sm Docker.raw
11588	Docker.raw
~/data % docker system df 
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          0         0         0B        0B
Containers      0         0         0B        0B
Local Volumes   0         0         0B        0B
Build Cache     1         0         0B        0B

// MEMO: 掃除コマンド実行後もファイルが残っている
... data % du -sm Docker.raw
11541	Docker.raw

```

## まとめ
:::note 
- Docker for Macでは、コンテナやイメージをdisk imageに保存する
- Dockerを落とした後、掃除コマンドを実行しても残ってしまうコンテナやイメージが存在しそう
- 掃除コマンドを実行しても解決しない時は、Docker Desktopから割当を減らしてみるのも良いかも
:::

まぁプラモデルとか組み立てて、それごと捨ててもなんか接着部分の破片が床に落ちてたりするみたいなそんな感じなのかな。

Dockerってムズカシイ。

### 参考文献
https://docs.docker.jp/config/pruning.html

https://docs.docker.jp/engine/reference/commandline/system_df.html

https://www.ibm.com/docs/ja/aix/7.1?topic=d-du-command

https://docs.docker.jp/desktop/mac/space.html

https://blog.pinkumohikan.com/entry/cleanup-docker-disk-image

## PR
株式会社HRBrainでは、一緒に働く仲間を募集しています！

興味を持っていただいた方はぜひ弊社の採用ページをご確認ください！

HRBrain文化を一緒に作っていきましょう！

https://www.hrbrain.co.jp/recruit/