Quantcast
Channel: 初心者タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 21089

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

$
0
0

はじめに

最近、くろかわこうへいさんや、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ホストディレクトリ
VolumeDocker のリソース
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:

参考


Viewing all articles
Browse latest Browse all 21089

Trending Articles