Dockerのボリュームとバインドマウントの違い

プログラミング

dockerのボリュームとバインドマウントの違い
dockerのボリュームとバインドマウントの違い

どうも、てーやまです。
今回も新たに学んだことを発信していきます。

今回は『マウント』についてです。内容に間違いがありましたら、コメントでご指摘頂けると嬉しいです。では、いってみましょう。

マウントとは

コンテナはホスト上で実行されるプロセスではありますが、ホストとは独立しています。よってコンテナ起動後に新規作成したファイルは、コンテナを削除すると消えてしまいます。

以下のようにubuntuイメージから作ったコンテナ削除で『test.txt』は消える。
$ docker run -it 74e834086a36 bash
root@ff62447c84b9:/# mkdir sample_dir
root@ff62447c84b9:/# touch sample_dir/test.txt
root@ff62447c84b9:/# ls sample_dir/
test.txt
root@ff62447c84b9:/# exit
exit
$ docker rm 7751419ad412
7751419ad412

ホストの資材をコンテナ内にマウントするということは、『ファイルやディレクトリを共有すること』だと捉えても間違いは無さそうです。

コンテナ内のファイルやディレクトリをホストと共有しているため、コンテナを削除しても編集内容が消えることはありません。

バインドマウントとボリューム

繰り返しになりますが、ホストのとある場所(ディレクトリやファイル)をコンテナにマウントさせておくことで、編集後のファイルを永続的に保存することができるようになります。

Dockerでのマウント方法は『ボリューム』と『バインドマウント』があり、ボリュームは『特定の場所(新規に作成したボリューム)』、バインドマウントは『どこでも』コンテナ内にマウントすることができます。

マウント機能の使い道

Ruby on Railsの開発におけるDockerマウントの使い道を考えてみました。

まず、自分の好きなエディタを利用できるのが1番のメリットな気がします。

コンテナ上のappディレクトリをマウントしておけば、コンテナに色々とインストールしたくない場合でも、自分の使い込んでいるエディタで書けるので便利だと思います。

ただ、上記はバインドマウントに限った話であり、ボリュームは『ファイルを永続的に保存する』機能のような気がします。

マウントのさせ方

いずれのマウント方法にしてもイメージからコンテナ起動時に、–mountまたは-vオプションを付けることでマウントできます。

しかしDockerドキュメントにあるように、–mountの方が項目順が順不同であるため、分かりやすいと思います。

バインドマウント

ホスト上のどのディレクトリでもマウントできるため、いきなりマウント元(ホスト)とマウント先(コンテナ)を指定できる。

$ mkdir host_dir
$ touch host_dir/host_file.txt
$ docker run -it --mount type=bind,source="$(pwd)"/host_dir,target=/home ubuntu bash
root@b02f5ce9865d:/# ls home/
host_file.txt

ボリューム

docker volume createコマンドによって明示的にボリュームを作成し、それをコンテナにマウントすると、コンテナ上で編集したファイルはこのボリュームに保存されます。コンテナを削除してもマウントして起動すれば引き続き編集できる訳です。

ボリュームの作成と確認
Mountpointが実際にボリュームの場所だが、これはDockerによって管理される
ホストからも直接アクセスすることはできない
$ docker volume create my-vol
$ docker volume inspect my-vol
[
    {
        "CreatedAt": "2020-08-13T14:38:42Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]
コンテナ起動後にマウントの状態を見ると、ボリュームにマウントされていることがわかる
$ docker run -it --mount type=volume,source=my-vol,target=/home ubuntu bash
$ docker inspect e01502ad99ab
"Mounts": [
            {
                "Type": "volume",
                "Name": "my-vol",
                "Source": "/var/lib/docker/volumes/my-vol/_data",
                "Destination": "/home",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }

マウント先の/homeに適当にtest.txtを作成した後にコンテナを削除して、
再度イメージから起動する際ボリュームにマウントすると、test.txtが存在していることが分かります。

root@e01502ad99ab:/# cd home
root@e01502ad99ab:/home# touch test.txt
root@e01502ad99ab:/home# exit
exit
$ docker rm e01502ad99ab
e01502ad99ab
daigonoMacBook-Pro:docker daigo$ docker run -it --mount type=volume,source=my-vol,target=/home ubuntu bash
root@e88d6a890f60:/# ls home/
test.txt