Edited at

Docker、ボリューム(Volume)について真面目に調べた


はじめに

Docker の Volume って難しくないですか?

理解に自信が無かった部分を、真面目に調べてまとめてみました。


これを読むとわかること



  • コンテナボリューム の違い


  • -v /aaa:/bbb-v /bbb-v ccc:/bbb の違い(docker-compose では volumes)


  • --volumes-from ddd の意味(docker-compose では volumes_from)

  • Data Volume と Data Volume Container の違い

  • Data Volume Container は、「永続化したいデータの保存先となるコンテナ」という意味ではない。(永続化したいデータの保存先はボリュームです)


ボリューム(Data Volume)とは



  • ボリュームとは、データを永続化できる場所のことである。


    • 外部HDDのようなイメージ。コンテナ本体にマウント(-v)して使う。




  • コンテナボリューム の違いについて


    • コンテナ内部にデータ(ファイル)を保存しても、コンテナ破棄すると消えてしまう。

    • なので、データを永続化したいときは、コンテナの外にデータを置く必要がある。

    • その場所のことを、ボリュームと呼ぶ。




  • ボリューム(=データを永続化できる場所) は2種類ある。


    • ホストのディレクトリ(ファイル)


      • ホストで ls で見えるモノ。



    • Docker の リソースとしての Volume



      • docker volume ls で見えるモノ。



    • (本当は、これ以外にもNFSなども指定できるようだ)



  • ボリュームをコンテナにマウントする(-v)ことで、コンテナからアクセスできるようになる。


  • あるいは--volumes-from <コンテナ名> とすると、指定したコンテナのマウントと同じようにマウントできる。(指定コンテナの -v の真似をする)





  • 以下コマンドを実行したとします。


    • 1 docker run -it --name c1 -v /hdir:/c1-hdir -v /hfile.txt:/c1-hfile.txt ubuntu:18.04 bash

    • 2 docker volume create v1

    • 3 docker run -it --name c2 -v v1:/c2-v1 ubuntu:18.04 bash

    • 4 docker run -it --name c3 --volumes-from c1 --volumes-from c2 ubuntu:18.04 bash



  • イメージは。


+--<Host>----------+   +--<Docker>-------------------------------------+

| | | +--<Container:c1>---+ +--<Volume:v1>-----+ |
| | | | | | | |
| /hdir/--------------------> /c1-hdir/ | | | |
| /hfile.txt----------------> /c1-hfile.txt | | | |
| | | | | | | |
| | | +-------------------+ | | |
| | | | | |
| | | +--<Container:c2>---+ | | |
| | | | | | | |
| | | | /c2-v1/ <-----------------/ | |
| | | | | | | |
| | | | | | | |
+------------------+ | +-------------------+ +------------------+ |
| |
| +--<Container:c3>-------------------------+ |
| | c1,c2 と同じものが同じ場所にマウントされる | |
| | /c1-hdir/ | |
| | /c1-hfile.txt | |
| | /c2-v1/ | |
| +-----------------------------------------+ |
+-----------------------------------------------+


  • このようになるので、コンテナ c1 c2 を破棄しても、データ元であるボリュームは保持されるので、消えない。

  • コンテナ c3c1 c2 のマウントポイントを持つ。(同じボリュームを同じマウントポイントにマウント)


  • メモ



    • docker volume create v1 は実行しなくてもいい。なぜなら -v v1:/c2-v1 しいたときに v1 が無ければ、自動で v1 が作られるから。


    • ボリューム名無し -v /c2-v1 でも自動的にボリュームが作成される。しかしながら、ボリューム名がハッシュ値になるので、docker volume ls してもどれが使われているのか分かりづらい。

      $ docker volume ls
      
      DRIVER VOLUME NAME
      local 35ad7529d3e1c981bbc2d9235b9e3e9f6f71aaf8143f5d80015a84db7bb06019・・・ボリューム名無しのとき
      local v1・・・ボリューム名有のとき



    • 実は 17.06 から --mount オプションが追加され、こちらが公式で推奨されている。






Data Volume Container とは



  • 「永続化したいデータの保存先となるコンテナ」という意味ではありません。


    • 私は勘違いしてましたorz




  • 公式サイトで、Data Volume Container という用語はヒットしませんでした。


    • 厳密には Container ≠ Volume なので、個人的にはこの用語には違和感があります。




  • 複数コンテナでボリュームをマウントするときの -v の記述を省略するテクニックなのだと理解しています。


    • 1 軽量なイメージ(busybox)を使って、ボリュームをマウント(-v)したコンテナを作っておく(これを Data Volume Container、あるいは Data Container と命名。このコンテナ自身は終了していてよい)

    • 2 新しいコンテナを作る時 --volumes-from <Data Volume Container> するだけで、ボリュームを同じマウントポイントで共有できる。




Docker Volume Container の利点がもう1つありました。--rm でボリューム削除されないようにできます。(2018/09/28追記)


  • 普通に docker run --rm ... するとコンテナ停止で、ボリュームも削除される。


    • 1 docker run -it --rm --name c2 -v /c2-v1 ubuntu:18.04 bash

    • 2 bashを抜けるとコンテナ停止となるので、コンテナ c1 ボリュームv1 が自動で削除される。



  • 上記の操作をしてもボリュームが残るようにしたいなら、先に Data Volume Conteiner を作っておけばよい。(コンテナにマウントされているボリュームは自動削除されない)

  • もっとも、Docker Volume Container を使わなくとも、ボリューム名有りマウント -v v1:/c2-v1 すれば --rm しても ボリューム v1 を残すことができる。


    • 1 docker run -it --rm --name c2 -v v1:/c2-v1 ubuntu:18.04 bash

    • 2 bashを抜けると、コンテナ c1 が削除される。ボリューム v1 は残る。




まとめ

ここまでのポイントを整理しておきます。


ボリュームとは、データを永続化できる場所のことである。

外部HDDのようなイメージ。コンテナ本体にマウント(-v)して使う。


コンテナ≠ボリューム(Data Volume) である。

コンテナ破棄しても、これにマウントされているボリュームは残る。


--volumes-from <コンテナ名> は「コンテナをマウント」しているのではない。

実は「指定コンテナのマウント(-v)のマネ」をしているだけ。マウントできるのはボリュームだけ。


永続化したいならボリューム名有りマウント -v v1:/c2-v1 を使うべき(2018/09/28記述見直し)


  • ボリューム名無しマウント -v /c2-v1 のデメリット


    • ボリューム名がハッシュ値になるので、docker volume ls してもどれが使われているのか分かりづらい。


    • --rm オプションを付けてコンテナ起動したとき、コンテナ破棄だけでなく ボリュームも削除されてしまう。



  • ボリューム名有りマウント -v v1:/c2-v1 を使えば、上記のデメリットはない。