2019-10-5追記
この記事を書いて1年が経ちましたが、実は今もほぼ毎日いいねやストックをもらっています。
やはり、Docker の Volume が気になる人は多いんだな、と感じています。
その一方、同じテーマで書いた 『[Docker] containerが使ってる全てのvolumeをCSV出力するワンライナー - Qiita』 は、未だに「1いいね」なのですが、どちらかと言えば、こちらの記事のほうが実践的なので、紹介しておきます。
具体的には「gitからcloneしてきてdocker-composeで起動したけど、これのコンテナとボリュームってどうつながってるの?」といった疑問の解決に使える思います
はじめに
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
)して使う。
- 外部HDDのようなイメージ。コンテナ本体にマウント(
-
コンテナ
とボリューム
の違いについて- コンテナ内部にデータ(ファイル)を保存しても、コンテナ破棄すると消えてしまう。
- なので、データを永続化したいときは、コンテナの外にデータを置く必要がある。
- その場所のことを、ボリュームと呼ぶ。
-
ボリューム
(=データを永続化できる場所) は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
- 1
-
イメージは。
+--<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
を破棄しても、データ元であるボリュームは保持されるので、消えない。 - コンテナ
c3
はc1
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
オプションが追加され、こちらが公式で推奨されている。- Use bind mounts | Docker Documentation https://docs.docker.com/storage/bind-mounts/#choosing-the--v-or---mount-flag
-
Data Volume Container とは
-
「永続化したいデータの保存先となるコンテナ」という意味ではありません。
- 私は勘違いしてましたorz
-
公式サイトで、Data Volume Container という用語はヒットしませんでした。
- 厳密には Container ≠ Volume なので、個人的にはこの用語には違和感があります。
-
複数コンテナでボリュームをマウントするときの
-v
の記述を省略するテクニックなのだと理解しています。- 1 軽量なイメージ(busybox)を使って、ボリュームをマウント(
-v
)したコンテナを作っておく(これを Data Volume Container、あるいは Data Container と命名。このコンテナ自身は終了していてよい) - 2 新しいコンテナを作る時
--volumes-from <Data Volume Container>
するだけで、ボリュームを同じマウントポイントで共有できる。
- 1 軽量なイメージ(busybox)を使って、ボリュームをマウント(
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
が自動で削除される。
- 1
- 上記の操作をしてもボリュームが残るようにしたいなら、先に 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
は残る。
- 1
まとめ
ここまでのポイントを整理しておきます。
ボリュームとは、データを永続化できる場所のことである。
外部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
を使えば、上記のデメリットはない。