docker volume調べた

dockerのvolumeについて調べた。

・dockerコンテナの内部データは削除時に消える。
・データ永続化のためにホストやdocker volumeというdockerが管理する領域をマウントする。
・マウントに指定したファイルやディレクトリはコンテナ削除した後も残る(データがコンテナ外部に保存されている感じ)
・マウントには二種類ある。hostのディレクトリを同期するタイプとdockerが管理するvolume空間をマウントするやつ。
・前者をバインドマウント, 後者をvolumeという。
・前者は開発中のコードをコンテナ内に同期して開発するのに使ったりする(エディタで編集しながらコンテナ内にコードを配置できる)。後者はホスト側で管理しなくても良い時に使う(mysqlのデータとかnginxとphpを繋ぐソケットファイルとか)


## 使い方 基本
docker run実行時に-v オプションでマウントできる
書式は-v ホストpath:コンテナpath。
ホストのpathに相対pathは使えないので絶対pathで書くこと。


```
↓a.txtを同期させる
$ docker run -it --rm -v ~/Documents/test/docker/volume_test/a.txt:/a.txt centos:centos8
[root@defef339acca /]# ls -la 
-rw-r--r--   1 root root    4 Dec 15 12:02 a.txt
略
```

ホスト側でa.txtを更新するとコンテナ側にも反映される。
また、コンテナ側から変更してもホスト側に反映される。

```
$ echo "aaa" > a.txt
↓コンテナ側
[root@defef339acca /]# cat a.txt 
aaa
```

ホスト側でa.txtを削除するとコンテナ側でバグる。ls -la だと存在するが、ファイルへのアクセスはできなくなる。

```
[root@defef339acca /]# ls -la 
-?????????   ? ?    ?       ?            ? a.txt
[root@defef339acca /]# cat a.txt 
cat: a.txt: No such file or directory

```

コンテナ側でa.txtを削除しようとするとエラーになる。ファイル編集は可能。

```
[root@57c0c3b18570 /]# rm a.txt 
rm: remove regular file 'a.txt'? yes
rm: cannot remove 'a.txt': Device or resource busy
```


a.txtがホスト側にない状態でマウントしようとすると、a.txtという名前でディレクトリが作成され、それがマウントされる。

```
[root@47850246319a /]# ls -la 
drwxr-xr-x   2 root root   64 Dec 15 12:12 a.txt
```

ファイルだけでなく、ディレクトリもマウントできる。
```
$ mkdir hoge
$ touch hoge/a.txt
$ docker run -it --rm -v ~/Documents/test/docker/volume_test/hoge:/hoge centos:centos8
[root@3c0109bbdf3c /]# ls -la 
drwxr-xr-x   3 root root   96 Dec 15 12:24 hoge
```

## 使い方 複数volumeマウント
-vオプションは複数使用できる。

```
$ docker run -it --rm -v ~/Documents/test/docker/volume_test/a.txt:/a.txt -v ~/Documents/test/docker/volume_test/b.txt:/b.txt centos:centos8
[root@19354f136991 /]# ls -la 
-rw-r--r--   1 root root    0 Dec 15 12:14 a.txt
-rw-r--r--   1 root root    0 Dec 15 12:14 b.txt
```


## 使い方 dockerボリュームをマウントする
-vオプションの値を変えることでdockerボリュームをマウントできる
ホストのディレクトリをマウントする際は絶対pathを使用したが、dockerボリュームをマウントする際はvolume名を指定する
-v volume名:コンテナpath

```
$ docker run -it --rm -v hoge:/hoge centos:centos8 
[root@31ac4d5be7fa /]# ls -la 
drwxr-xr-x   2 root root 4096 Dec 15 12:40 hoge
[root@31ac4d5be7fa /]# touch hoge/a.txt
[root@31ac4d5be7fa /]# exit

--rmをつけてコンテナ起動しているのでexit時にコンテナは破棄される。
↓再度コンテナを作成する
$ docker run -it --rm -v hoge:/hoge centos:centos8 

↓hogeはdockerボリュームになっているので永続化されていることが分かる。
[root@4c03049e11c9 /]# ls hoge
a.txt
```

docker volumeをコマンドで確認する

```
$ docker volume ls 
DRIVER    VOLUME NAME
local     hoge
```

dockerボリュームをマウントする際はvolume名を指定しなくても良い。
volume名を指定しないvolumeを匿名ボリュームという。
その場合は、コンテナpathだけ指定する。
-v コンテナpath

```
$ docker run -it --rm -v /fuga centos:centos8 
[root@6806bc7b9bcf /]# ls -la 
drwxr-xr-x   2 root root 4096 Dec 15 12:44 fuga
```

ただし、volume名を指定しないとvolume名はハッシュ値となり何のvolumeなのか分かりづらくなるのでおすすめしない。

```
$ docker volume ls 
DRIVER    VOLUME NAME
local     16fba3a332888fcd049a7dd569d6d27f360cc07ef58000bfee93f25e85416df9
```

また、volume名をつけない + --rm付きで起動した場合、コンテナ内でディレクトリは作成されたがvolumeは作成されず永続化されなかった。--rmなしでやるとvolumeが作成された。
(あれ、こんな挙動だったっけ？)


## docker volumeコマンド
docker volumeコマンドには以下がある。

```
$ docker volume 

Usage:  docker volume COMMAND

Manage volumes

Commands:
  create      Create a volume
  inspect     Display detailed information on one or more volumes
  ls          List volumes
  prune       Remove all unused local volumes
  rm          Remove one or more volumes

Run 'docker volume COMMAND --help' for more information on a command.
```

ls でvolume一覧を表示する。
prune で未使用のローカルvolume削除
rm で特定のvolume削除


## docker volume inspectについて
inspect = 検査。
volumeの詳細情報を教えてくれるらしい。
Mountpointを見るとvolumeがどこに格納されているか分かる。このpathはmac上のpathではなくdocker engineが動いているvm上のpath。

```
$ docker volume ls 
DRIVER    VOLUME NAME
local     16fba3a332888fcd049a7dd569d6d27f360cc07ef58000bfee93f25e85416df9
local     bbb
local     hoge

$ docker volume inspect hoge
[
    {
        "CreatedAt": "2020-12-15T12:40:52Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/hoge/_data",
        "Name": "hoge",
        "Options": null,
        "Scope": "local"
    }
]

```


## 参考
公式
https://matsuand.github.io/docs.docker.jp.onthefly/storage/volumes/