これは何?
- dockerやdocker-composeで多くのコンテナを動かすと、「このvolumeは、どのconteinerで使ってるんだ?」と悩むことがあります。
- 当初は
docker volume inspect <ボリューム名>
で、調べられるんじゃないかと思っていたのですが、残念ながらこの方法では「そのvolumeが、どのcontainerで使われているか」は表示されませんでした。 - 代わりに Dockerfile や docker-compose.yml を grep したり、
docker container inspect <コンテナ名>
で調べてましたが、毎回これをするのは手間がかかります。
解決方法
- ワンライナーを考えました。以下の通りです。
-
jq
を使ってますので、事前にapt install jq
などしておいてください。 - 出力はCSVで、Name(コンテナ名)、Type(bind or volume)、Src(ホストリソース)、Dst(コンテナ側リソース) の順です。
- Type=bind は、ホストのファイル(フォルダ)をコンテナへマウント
- Type=volumeは、ボリュームをコンテナへマウントを意味します。
-
$ docker ps -a --format "{{.Names}}" | xargs docker inspect | jq -r '["Name","Type","Src","Dst"], (.[] | { Name:.Name, Mounts:.Mounts[] } | [ .Name, .Mounts.Type, .Mounts.Source, .Mounts.Destination ]) | @csv'
"Name","Type","Src","Dst"
"/c4x","bind","/tmp","/mount/tmp"
"/c4x","volume","/var/lib/docker/volumes/cc445a32103d6285d6f62694a74016c61255bbfbdcb4bed018ecda82f72f48fa/_data","/mount/unnamedvolume"
"/c4x","volume","/var/lib/docker/volumes/nemedvolume/_data","/mount/namedvolume"
"/c4","volume","/var/lib/docker/volumes/1543500c35fd8a7d4a63abf281733a83eac0ae4f863f36bda31f3d1aff1200d5/_data","/mount/unnamedvolume"
"/c4","volume","/var/lib/docker/volumes/nemedvolume/_data","/mount/namedvolume"
"/c4","bind","/tmp","/mount/tmp"
"/c3x","bind","/tmp","/mount/tmp"
"/c3","bind","/tmp","/mount/tmp"
"/c2x","volume","/var/lib/docker/volumes/nemedvolume/_data","/mount/namedvolume"
"/c2","volume","/var/lib/docker/volumes/nemedvolume/_data","/mount/namedvolume"
"/c1x","volume","/var/lib/docker/volumes/cc445a32103d6285d6f62694a74016c61255bbfbdcb4bed018ecda82f72f48fa/_data","/mount/unnamedvolume"
"/c1","volume","/var/lib/docker/volumes/1543500c35fd8a7d4a63abf281733a83eac0ae4f863f36bda31f3d1aff1200d5/_data","/mount/unnamedvolume"
参考、解決方法に至るまでの過程
docker volume inspect で調べてみる(期待した結果を得られず)
- ある時、volumeの一覧を見てみました。
$ docker volume ls
DRIVER VOLUME NAME
local 1543500c35fd8a7d4a63abf281733a83eac0ae4f863f36bda31f3d1aff1200d5
local cc445a32103d6285d6f62694a74016c61255bbfbdcb4bed018ecda82f72f48fa
local nemedvolume
$
-
1543500c35・・・
って誰が使ってるんだろう? - dockerコマンドのお決まりパターンとして、各リソースは
inspect
で詳細が見られるので、これを使ってみます。
$ docker volume inspect 1543500c35fd8a7d4a63abf281733a83eac0ae4f863f36bda31f3d1aff1200d5
[
{
"CreatedAt": "2019-04-01T00:28:19+09:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/1543500c35fd8a7d4a63abf281733a83eac0ae4f863f36bda31f3d1aff1200d5/_data",
"Name": "1543500c35fd8a7d4a63abf281733a83eac0ae4f863f36bda31f3d1aff1200d5",
"Options": null,
"Scope": "local"
}
]
- 残念ながらこの方法(volume inspect)では、どの container が使っているかという情報は、表示されませんでした。
各 container が使用している volume をリストアップするワンライナー
- アプローチを変えて、conteiner inspect から、volume を抽出してみます。
-
jq
を使ってますので、事前にapt install jq
などしておいてください。
-
$ docker ps -a --format "{{.Names}}" | xargs docker inspect | jq -r '["Name","Type","Src","Dst"], (.[] | { Name:.Name, Mounts:.Mounts[] } | [ .Name, .Mounts.Type, .Mounts.Source, .Mounts.Destination ]) | @csv'
"Name","Type","Src","Dst"
"/c4x","bind","/tmp","/mount/tmp"
"/c4x","volume","/var/lib/docker/volumes/cc445a32103d6285d6f62694a74016c61255bbfbdcb4bed018ecda82f72f48fa/_data","/mount/unnamedvolume"
"/c4x","volume","/var/lib/docker/volumes/nemedvolume/_data","/mount/namedvolume"
★"/c4","volume","/var/lib/docker/volumes/1543500c35fd8a7d4a63abf281733a83eac0ae4f863f36bda31f3d1aff1200d5/_data","/mount/unnamedvolume"
"/c4","volume","/var/lib/docker/volumes/nemedvolume/_data","/mount/namedvolume"
"/c4","bind","/tmp","/mount/tmp"
"/c3x","bind","/tmp","/mount/tmp"
"/c3","bind","/tmp","/mount/tmp"
"/c2x","volume","/var/lib/docker/volumes/nemedvolume/_data","/mount/namedvolume"
"/c2","volume","/var/lib/docker/volumes/nemedvolume/_data","/mount/namedvolume"
"/c1x","volume","/var/lib/docker/volumes/cc445a32103d6285d6f62694a74016c61255bbfbdcb4bed018ecda82f72f48fa/_data","/mount/unnamedvolume"
★"/c1","volume","/var/lib/docker/volumes/1543500c35fd8a7d4a63abf281733a83eac0ae4f863f36bda31f3d1aff1200d5/_data","/mount/unnamedvolume"
-
1543500c35・・・
を使っているのは、c1
c4
コンテナでした。 (行頭★印)
参考、検証するのに使ったスクリプト
# c1: 名前無しボリューム
docker container run -d -v /mount/unnamedvolume --name c1 alpine tail -f /dev/null
docker container run -d --mount type=volume,target=/mount/unnamedvolume --name c1x alpine tail -f /dev/null
# c2: 名前有りボリューム
docker container run -d -v nemedvolume:/mount/namedvolume --name c2 alpine tail -f /dev/null
docker container run -d --mount type=volume,source=nemedvolume,target=/mount/namedvolume --name c2x alpine tail -f /dev/null
# c3: ローカルフォルダをマウント
docker container run -d -v /tmp:/mount/tmp --name c3 alpine tail -f /dev/null
docker container run -d --mount type=bind,source=/tmp,target=/mount/tmp --name c3x alpine tail -f /dev/null
# c4: c1,c2,c3 と同じものを自分にマウント
docker container run -d --volumes-from c1 --volumes-from c2 --volumes-from c3 --name c4 alpine tail -f /dev/null
docker container run -d --volumes-from c1x --volumes-from c2x --volumes-from c3x --name c4x alpine tail -f /dev/null
# 全コンテナのボリューム、マウント状況
docker ps -a --format "{{.Names}}" | xargs docker inspect | jq -r ".[] | { Name:.Name, Status:.State.Status, Mounts:.Mounts, Binds:.HostConfig.Binds }"
#
docker container ps --all
docker volume ls
# 全コンテナ停止
docker stop $(docker ps -aq)
# 停止コンテナ削除、未使用ボリューム削除など
docker system prune --volumes
- 実行結果
$ # c1: 名前無しボリューム
$ docker container run -d -v /mount/unnamedvolume --name c1 alpine tail -f /dev/null
39476806bd6de03df0959bb3a3090e0578b7195041d59b8d9dfd496f53ab8788
$ docker container run -d --mount type=volume,target=/mount/unnamedvolume --name c1x alpine tail -f /dev/null
f9ff47a6e53e5f13503c4fefe4d25cee38b6aff40fdb4d1a8be00b4bdad2b792
$
$ # c2: 名前有りボリューム
$ docker container run -d -v nemedvolume:/mount/namedvolume --name c2 alpine tail -f /dev/null
c5d02e034ba4131017a306023ed709ec4eb58716d2096419cb5f42457f074f47
$ docker container run -d --mount type=volume,source=nemedvolume,target=/mount/namedvolume --name c2x alpine tail -f /dev/null
83aaa13c98846accef04c4866ce421896d6483d3d6ad279a68a4bd3f46b34e79
$
$ # c3: ローカルフォルダをマウント
$ docker container run -d -v /tmp:/mount/tmp --name c3 alpine tail -f /dev/null
fc5499024b21e6eb2198668b3fbfe17d36f1d8bc8979ae366c5e7c9a8ba6b178
$ docker container run -d --mount type=bind,source=/tmp,target=/mount/tmp --name c3x alpine tail -f /dev/null
14e026db8f80ae011ea95c9b6a7ea07d8ebddf0f1f2b6d0a83b3cb9cbd90159c
$
$ # c4: c1,c2,c3 と同じものを自分にマウント
$ docker container run -d --volumes-from c1 --volumes-from c2 --volumes-from c3 --name c4 alpine tail -f /dev/null
c5d7f45ec7e42099692a446f65e64a40389342ac0e225811bed4c798817309bd
$ docker container run -d --volumes-from c1x --volumes-from c2x --volumes-from c3x --name c4x alpine tail -f /dev/null
7a3823a7c0421d3c56d101301caa79c2542eadbd1177f9bab93caeed5184629f
$
$ # 全コンテナのボリューム、マウント状況
$ docker ps -a --format "{{.Names}}" | xargs docker inspect | jq -r ".[] | { Name:.Name, Status:.State.Status, Mounts:.Mounts, Binds:.HostConfig.Binds }"
{
"Name": "/c4x",
"Status": "running",
"Mounts": [
{
"Type": "volume",
"Name": "31712e5037e79400b29fa2d58369845bdb1c56a8ca34e7b34da1842e5a65c6ee",
"Source": "/var/lib/docker/volumes/31712e5037e79400b29fa2d58369845bdb1c56a8ca34e7b34da1842e5a65c6ee/_data",
"Destination": "/mount/unnamedvolume",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "nemedvolume",
"Source": "/var/lib/docker/volumes/nemedvolume/_data",
"Destination": "/mount/namedvolume",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "bind",
"Source": "/tmp",
"Destination": "/mount/tmp",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"Binds": null
}
{
"Name": "/c4",
"Status": "running",
"Mounts": [
{
"Type": "volume",
"Name": "cc056258411e7f796fbdc682a34079a241cd3bb9f52e8d9e697b1d3e7c5eaf7c",
"Source": "/var/lib/docker/volumes/cc056258411e7f796fbdc682a34079a241cd3bb9f52e8d9e697b1d3e7c5eaf7c/_data",
"Destination": "/mount/unnamedvolume",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "volume",
"Name": "nemedvolume",
"Source": "/var/lib/docker/volumes/nemedvolume/_data",
"Destination": "/mount/namedvolume",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
},
{
"Type": "bind",
"Source": "/tmp",
"Destination": "/mount/tmp",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"Binds": null
}
{
"Name": "/c3x",
"Status": "running",
"Mounts": [
{
"Type": "bind",
"Source": "/tmp",
"Destination": "/mount/tmp",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"Binds": null
}
{
"Name": "/c3",
"Status": "running",
"Mounts": [
{
"Type": "bind",
"Source": "/tmp",
"Destination": "/mount/tmp",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"Binds": [
"/tmp:/mount/tmp"
]
}
{
"Name": "/c2x",
"Status": "running",
"Mounts": [
{
"Type": "volume",
"Name": "nemedvolume",
"Source": "/var/lib/docker/volumes/nemedvolume/_data",
"Destination": "/mount/namedvolume",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
"Binds": null
}
{
"Name": "/c2",
"Status": "running",
"Mounts": [
{
"Type": "volume",
"Name": "nemedvolume",
"Source": "/var/lib/docker/volumes/nemedvolume/_data",
"Destination": "/mount/namedvolume",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
"Binds": [
"nemedvolume:/mount/namedvolume"
]
}
{
"Name": "/c1x",
"Status": "running",
"Mounts": [
{
"Type": "volume",
"Name": "31712e5037e79400b29fa2d58369845bdb1c56a8ca34e7b34da1842e5a65c6ee",
"Source": "/var/lib/docker/volumes/31712e5037e79400b29fa2d58369845bdb1c56a8ca34e7b34da1842e5a65c6ee/_data",
"Destination": "/mount/unnamedvolume",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
"Binds": null
}
{
"Name": "/c1",
"Status": "running",
"Mounts": [
{
"Type": "volume",
"Name": "cc056258411e7f796fbdc682a34079a241cd3bb9f52e8d9e697b1d3e7c5eaf7c",
"Source": "/var/lib/docker/volumes/cc056258411e7f796fbdc682a34079a241cd3bb9f52e8d9e697b1d3e7c5eaf7c/_data",
"Destination": "/mount/unnamedvolume",
"Driver": "local",
"Mode": "",
"RW": true,
"Propagation": ""
}
],
"Binds": null
}
$
$ #
$ docker container ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7a3823a7c042 alpine "tail -f /dev/null" 1 second ago Up Less than a second c4x
c5d7f45ec7e4 alpine "tail -f /dev/null" 2 seconds ago Up 1 second c4
14e026db8f80 alpine "tail -f /dev/null" 3 seconds ago Up 2 seconds c3x
fc5499024b21 alpine "tail -f /dev/null" 4 seconds ago Up 3 seconds c3
83aaa13c9884 alpine "tail -f /dev/null" 5 seconds ago Up 4 seconds c2x
c5d02e034ba4 alpine "tail -f /dev/null" 6 seconds ago Up 5 seconds c2
f9ff47a6e53e alpine "tail -f /dev/null" 7 seconds ago Up 6 seconds c1x
39476806bd6d alpine "tail -f /dev/null" 8 seconds ago Up 7 seconds c1
$ docker volume ls
DRIVER VOLUME NAME
local 31712e5037e79400b29fa2d58369845bdb1c56a8ca34e7b34da1842e5a65c6ee
local cc056258411e7f796fbdc682a34079a241cd3bb9f52e8d9e697b1d3e7c5eaf7c
local nemedvolume
$
$ # 全コンテナ停止
$ docker stop $(docker ps -aq)
7a3823a7c042
c5d7f45ec7e4
14e026db8f80
fc5499024b21
83aaa13c9884
c5d02e034ba4
f9ff47a6e53e
39476806bd6d
$
$ # 停止コンテナ削除、未使用ボリューム削除など
$ 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 build cache
Are you sure you want to continue? [y/N] y
Deleted Containers:
7a3823a7c0421d3c56d101301caa79c2542eadbd1177f9bab93caeed5184629f
c5d7f45ec7e42099692a446f65e64a40389342ac0e225811bed4c798817309bd
14e026db8f80ae011ea95c9b6a7ea07d8ebddf0f1f2b6d0a83b3cb9cbd90159c
fc5499024b21e6eb2198668b3fbfe17d36f1d8bc8979ae366c5e7c9a8ba6b178
83aaa13c98846accef04c4866ce421896d6483d3d6ad279a68a4bd3f46b34e79
c5d02e034ba4131017a306023ed709ec4eb58716d2096419cb5f42457f074f47
f9ff47a6e53e5f13503c4fefe4d25cee38b6aff40fdb4d1a8be00b4bdad2b792
39476806bd6de03df0959bb3a3090e0578b7195041d59b8d9dfd496f53ab8788
Deleted Volumes:
nemedvolume
cc056258411e7f796fbdc682a34079a241cd3bb9f52e8d9e697b1d3e7c5eaf7c
31712e5037e79400b29fa2d58369845bdb1c56a8ca34e7b34da1842e5a65c6ee
Total reclaimed space: 0B
$