[Docker] docker system prune --volumes で永続化ボリュームの誤削除を避ける


docker で永続化データを扱うには、ホスト上のディレクトリにマウントするのが簡単ですが、docker では docker volume の利用を推奨しています。

そこで docker volume を試してみたところ、ひとつ問題点が。

`docker system prune --volumes` コマンドで不要なリソースを削除しようとすると、名前付きで作成したボリュームも削除されてしまう！

```bash
$ docker volume create vol1_normal  # ★名前付きボリュームを作成
vol1_normal
$ docker volume ls
DRIVER              VOLUME NAME
local               vol1_normal

$ docker system prune --volumes
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all volumes not used by at least one container
  - all dangling images
  - all dangling build cache

Are you sure you want to continue? [y/N] y

Deleted Volumes:
vol1_normal

Total reclaimed space: 0B

$ docker volume ls
DRIVER              VOLUME NAME  # ★名前付きボリュームも消えてしまう
```


`docker system prune --volumes` では未使用のボリュームを削除するとあるのですが、何をもって「未使用」と判定するかというと、「コンテナから利用されていない」もののようです。
なので、メンテナンスなどでコンテナを停止している状態だと、ボリュームが削除されてしまいます。。

データの永続化に docker volume の利用を推奨しておいて、この振る舞いは危険すぎます。

利用者視点からは、以下のような振る舞いが理想です。

- 無名ボリュームなどは削除したいので `--volumes` オプションは使いたい！
- 名前付きで作成したボリュームは明示的に指定しない限りは勝手に削除して欲しくない！

`docker system prune` には `--filter` オプションがあるので、これとラベルを使って、永続化指定したものは除外することはできます。

```bash
$ docker volume create vol1_normal
vol1_normal
$ docker volume create vol1_persistence --label persistence=true  # ★永続化指定のラベルを付与
vol1_persistence
$ docker volume ls
DRIVER              VOLUME NAME
local               vol1_normal
local               vol1_persistence

$ docker system prune --volumes --filter label!=persistence=true  # ★永続化指定ありを除外するよう filter 指定
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all volumes not used by at least one container
  - all dangling images
  - all dangling build cache

  Items to be pruned will be filtered with:
  - label!=persistence=true

Are you sure you want to continue? [y/N] y
Deleted Volumes:
vol1_normal

Total reclaimed space: 0B

$ docker volume ls
DRIVER              VOLUME NAME
local               vol1_persistence  # ★永続化指定ありのボリュームを残せた
```


ただ、この方法では毎回 `--filter` オプションを付けるのが面倒ですし、エリアス設定やツールを用意したとしても、それの使用を徹底させるのは困難です。

やはり、自然に `docker system prune --volumes` と実行できるのが理想です。

何かデフォルト設定する方法がないか調べてみると、`~/.docker/config.json` で `pruneFilters` を指定できることが分かりました。
ドキュメントには見当たらず、ソースを読んでみて見つけました。。ひどい。

```~/.docker/config.json
{
        "pruneFilters": [
                "label!=persistence=true"
        ]
}
```


これで期待通りの振る舞いになりました。

```bash
$ docker volume create vol1_normal
vol1_normal
$ docker volume create vol1_persistence --label persistence=true
vol1_persistence
$ docker volume ls
DRIVER              VOLUME NAME
local               vol1_normal
local               vol1_persistence

$ docker system prune --volumes  # ★prune のコマンドの filter 指定なし
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all volumes not used by at least one container
  - all dangling images
  - all dangling build cache

  Items to be pruned will be filtered with:  # ★デフォルトの filter 指定が有効になる
  - label!=persistence=true

Are you sure you want to continue? [y/N] y
Deleted Volumes:
vol1_normal

Total reclaimed space: 0B

$ docker volume ls
DRIVER              VOLUME NAME
local               vol1_persistence  # ★永続化指定ありのボリュームを残せた
```


でも、やっぱり docker 本体で改善してもらいたいですね。


// EOF