docker で永続化データを扱うには、ホスト上のディレクトリにマウントするのが簡単ですが、docker では docker volume の利用を推奨しています。
そこで docker volume を試してみたところ、ひとつ問題点が。
docker system prune --volumes
コマンドで不要なリソースを削除しようとすると、名前付きで作成したボリュームも削除されてしまう!
$ 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
オプションがあるので、これとラベルを使って、永続化指定したものは除外することはできます。
$ 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
を指定できることが分かりました。
ドキュメントには見当たらず、ソースを読んでみて見つけました。。ひどい。
{
"pruneFilters": [
"label!=persistence=true"
]
}
これで期待通りの振る舞いになりました。
$ 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