3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Docker volume の公式ドキュメントが分かりやすかった話

Posted at

はじめに

最近、くろかわこうへいさんや、KENTAさんの動画をよく見る中で「あれ、Docker できないのやばくね?」と、ふと思いDocker の学習を始めました。参考書やネットでちょっと調べていくと「あれ、思ってたよりも難しくないじゃん」と思っていた矢先に、volume が出てきて一気につまづきまいした。記事などもいろいろ読んで調べてみたものの、よくわからず挫折しかけていた時に、公式ドキュメントに出会い読んでみると「何これわかりやすいじゃん!」ってなりました(笑)。

ということで、公式ドキュメントを読んで自分なりに理解したことをまとめます。

実行環境

  • Windows Home 10
  • Docker Toolbox v19.03.1

この記事を読むとわかること

  • volume とは
  • Dockerをデータの永続化の具体的な方法
  • データのマウントの具体的な挙動及び実装方法
    • bind mount
    • volume
    • tmpfs mount

Volume には 2 つの意味がある

後述するが、データを永続化させる方法は bind mountvolume の2 種類ある。ただ、どちらも -v--volume を使う。つまり、volume という単語には 2 つの意味があることになる。

  • データをマウントするための機能(-v, --volume)
  • Dockerのリソース内にあるコンテナの実行データを保管する場所

この記事では前者の機能を示す volume を データのマウントと定義する。

なぜデータのマウントが必要か

そもそもなぜ、データのマウントが必要なのか?

それは、コンテナ内部にデータを保存しても、コンテナ破棄すると消えてしまうため、データを永続化する際は、コンテナの外にデータを置く必要があるため。

データをマウント方法は 3 つ

概要

データのマウント方法は 3 つある。データを永続化させる場合は Bind mountVolume を使う。

  • Bind mount
  • Volume
  • Tmpfs mount
種類 データの保管場所 永続化
Bind mount ホストディレクトリ
Volume Docker のリソース
Tmpfs mount メモリ ×

data-mount
出典:docker docs

Bind mount

  • 特徴

    • ホストディレクトリやファイルがコンテナにマウントされる
    • コンテナ内のデータの変更に応じてホスト側のファイルも変更される
  • 用途

    • データを永続化させたい

    • 開発環境でホスト側のソースコードの修正を反映させたい

      ※ 本番環境のイメージではマウントでデータをコンテナに反映させるのではなく、`copy`を使うことが推奨されている。
      
  • 実装方法

    • -v または --volume を使う

       オプションの設定が **1 つ**のフィールドに固まっており、コンテナにデータのマウント先のディレクトリがなければ**自動的に作成**される。
      
    • --mount を使う

       オプションの設定が**複数**のフィールドに分かれているコンテナにマウント先のディレクトリが無ければ、**エラー**を返す。(※筆者の環境ではディレクトリが自動作成された)
      

  • volume_testディレクトリをマウントしてみる。ディレクトリの中は text.txt のみ。

volume_test
    test.txt

テキストファイルの内容。

test.txt
test

volume_testディレクトリに移動する。

まずは、-v--volume)コマンドでカレントディレクトリを ubuntu コンテナ内のすでに存在する /usr/src/var/tmp にマウントしてみる。

> docker run -it --name bindmount -v $(pwd):/usr/src/var/tmp ubuntu bash
root@eab26b27a693:/# cd usr/src/var/tmp
root@eab26b27a693:/usr/src/var/tmp# ls
test.txt

きちんと ディレクトリのデータがマウントされていることが分かる。ファイルの内容もtest から mount success! に変更してみる。

root@eab26b27a693:/usr/src/var/tmp# cat test.txt
test
root@eab26b27a693:/usr/src/var/tmp# echo mount success! > test.txt
root@eab26b27a693:/usr/src/var/tmp# cat test.txt
mount success!

実際にホスト側のファイルを確認してみると変更が反映されている!

次に、 ubuntu コンテナ内に存在しない /volume_test にマウントしてみる。

> docker run -it --name bindmount -v $(pwd):/volume_test ubuntu bash
root@b3e9bf711b7e:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume_test
root@b3e9bf711b7e:/# cd volume_test
root@b3e9bf711b7e:/volume_test# ls
test.txt

存在しないディレクトリにマウントした際には新しくディレクトリが作られている。先程と同様にファイルの内容もtest から mount success! に変更してみる。

root@b3e9bf711b7e:/volume_test# cat test.txt
test
root@b3e9bf711b7e:/volume_test# echo mount success! > test.txt
root@b3e9bf711b7e:/volume_test# cat test.txt
mount success!

こちらでもホスト側のファイルを確認してみると変更が反映されている!

次に --mount コマンドでカレントディレクトリを ubuntu 内のすでに存在する /usr/src/var/tmp にマウントしてみる。-v とは違いマウントの仕方やホスト側のディレクトリ、マウントのディレクトリといった複数のオプションをカンマつなぎで記述する。

> docker run -it --name bindmount --mount type=bind,source="$(pwd)",target=/usr/src/var/tmp ubuntu bash
root@f77d388c204e:/# cd usr/src/var/tmp
root@f77d388c204e:/usr/src/var/tmp# ls
test.txt

--mount を使った場合でも同様にマウントできた。実際にコンテナ内のファイルを編集した際は上記の内容と同様に、ホスト側のファイルも編集された。

次に、ubuntu コンテナに存在しないディレクトリ( volume_test )にマウントしてみる。

docker run -it --rm --name bindmount --mount type=bind,source="$(pwd)",target=/volume_test ubuntu bash
root@a738ae0ebbd0:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var  volume_test

volume_test が存在している!!! マウントできた!?

公式ドキュメントによると、

If you use --mount to bind-mount a file or directory that does not yet exist on the Docker host, Docker does not automatically create it for you, but generates an error.
出典:docker docs

つまり、--mount を使ってコンテナにバインドマウントする際は、コンテナ内にすでに存在するディレクトリにマウントしないとエラーが出る。なぜできたのだろう??

バインドマウントできているか確かめてみる。

root@a738ae0ebbd0:/# cd volume_test/
root@a738ae0ebbd0:/volume_test# cat test.txt
test
root@a738ae0ebbd0:/volume_test# echo mount sucess! > test.txt
root@a738ae0ebbd0:/volume_test# cat test.txt
mount sucess!

ホスト側のファイルも変更されているので、バインドマウントができている。なぜだろう??

ちなみに-v, --mmount どちらを使ってもマルチコンテナ間でもデータの共有は可能。

Volume

  • 特徴

    • docker リソース内のデータがコンテナにマウントされる
    • ホストディレクトリに依存しない
  • 用途

    • データを永続化させたい
    • 開発環境でソースコードの修正を反映させる以外の目的
  • 実装方法
    bind mount と同じ。-v または --mount を使う。


  • まずは volume_test という名前のボリュームを作る。

$ docker volume create volume_test
volume_test
$ docker volume ls
local               volume_test

まずは、-v--volume)コマンドでカレントディレクトリを ubuntu コンテナ内のすでに存在する /usr/src/var/tmp にマウントしてみる。また、ボリュームが存在しない場合は自動でボリュームが作成される。test.txt に mount success! と入力してコンテナを閉じる。

$ docker run -it --name volume_mount -v volume_test:/usr/src/var/tmp ubuntu bash                                        root@fe23da2e739c:/# cd /usr/src/var/tmp
root@fe23da2e739c:/usr/src/var/tmp# ls
root@fe23da2e739c:/usr/src/var/tmp# touch test.txt
root@fe23da2e739c:/usr/src/var/tmp# echo mount success! > test.txt
root@fe23da2e739c:/usr/src/var/tmp# cat test.txt
mount success!
root@fe23da2e739c:/usr/src/var/tmp# exit

コンテナを再度立ち上げて、test.txtが存在するか確認してみる。

$ docker container rm volume_mount
volume_mount
$ docker run -it --name volume_mount -v volume_test:/usr/src/var/tmp ubuntu bash
root@e54d18741135:/# cat usr/src/var/tmp/test.txt
mount success!

マウントできている!ubuntu コンテナに存在しないディレクトリにマウントしても同様の結果が得られる。

次に、次に --mount コマンドでカレントディレクトリを ubuntu 内のすでに存在する /usr/src/var/tmp にマウントしてみる。先程と同様に、test.txt に mount success! と入力してコンテナを閉じる。

$ docker run -it --name volume_mount --mount source="volume_test",target=/usr/src/var/tmp ubuntu bash                   
root@03074d3166a9:/# echo > usr/src/var/tmp/test.txt
root@03074d3166a9:/# cat usr/src/var/tmp/test.txt

root@03074d3166a9:/# echo mount success! > usr/src/var/tmp/test.txt
root@03074d3166a9:/# cat usr/src/var/tmp/test.txt
mount success!
root@03074d3166a9:/# exit

再度、volume_test をマウントしてコンテナを立ち上げる。

$ docker run -it --name volume_mount --mount source="volume_test",target=/usr/src/var/tmp ubuntu bash
root@9fe26cd9575f:/# cat usr/src/var/tmp/test.txt
mount success!

マウントできている!ubuntu コンテナに存在しないディレクトリにマウントしても同様の結果が得られる。

ちなみに-v, --mmount どちらを使ってもマルチコンテナ間でもデータの共有は可能。

Tmpfs mount

  • 特徴

    • マルチコンテナ間でデータの共有はできない
    • コンテナが止まるとホストメモリ上に保存されたファイルは消える
    • Docker on Linux でのみ動作する
  • 用途

    • 一時的にデータを退避させたい
    • セキュリティ的な理由で、ホストディレクトリやDocker リソース内の書き込み可能な領域にファイルを保管したくない
  • 実装方法

    • -tmpfs を使う

       マウントディレクトリ以外のオプションの設定が不可、コンテナにデータのマウント先のディレクトリがなければ**自動的に作成**される。
      
    • --mount を使う

       オプションの設定が**複数**のフィールドに分かれているコンテナにマウント先のディレクトリが無ければ、**エラー**を返す。
      

まとめ

  • データの永続化の種類は二つ
    • bind mount
    • volume

それぞれの違いは、永続化データの保存領域。使い分けは、開発においてソースコードの修正をコンテナにも反映させたいといったホストOSのファイルに依存することなら bind mount そうでなければ、volume を使う。

  • 一時的にデータを退避させるなら tmpfs mount を使う。

初心者なので、至らぬところはあるかと思いますがご指摘いただいたけると幸いです :bow_tone1:

参考

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?