こんにちは!サーバサイドを勉強中のこのぴーです
PlayGroundアドベントカレンダー8日目の記事になります
Dockerで開発している際にVolumesやBind mountなどを使う機会があると思いますが、それぞれの違いをちゃんと理解して使い分けできていないこともあるかもしれません
今回は違いや使い分けあたりを解説していきたいと思います
Volumes・Bind mount・tmpfs mountに共通していること
これらの3つに共通しているのはデータをコンテナの外、すなわちホストマシン側に保持する点です
ローカルでの開発中に出る本番環境には不要なデータをイメージに残したくないときなどに使います
3つともホストマシンにデータを保持しますが、コンテナ停止後も保存されるのはVolumesとBind mountだけで、tmpfs mountはホストシステムメモリ内に保存されるためコンテナ停止後はデータが残りません
ホスト上のどこに保存されるのか
どのマウント方法を利用してもコンテナ内からの見え方や同じです
じゃあ何が違うの?ということなんですが、ホストマシン上のどこにデータが保存されるのかという違いになります
Volumes
Volumesの場合はホストのファイルシステム上のDockerに管理されたディレクトリに保存されます
(Linuxだと/var/lib/docker/valumes/
)
Bind mount
Bind mountの場合はホストのファイルシステム上の好きな場所に保存することができます
tmpfs mount
tmpfs mountの場合はホストのメモリ上にだけ保存されます
それぞれの詳細
3つのマウント方法の詳細な違いについてみていきます
Volumes
Volumesはコンテナで生成されたデータを永続的に保持するために使用しますbind mountはホストマシンのディレクトリ構造に依存しますがvolumesはDockerが管理します
そのため、バックアップや移行がしやすかったり複数コンテナ間で安全に共有できたりします
また、Docker Desktop上のボリュームはMacやWindowsからのbind mountに比べて性能が高いです
実際にvolumeを作成してみます
以下のコマンドでvolume-testという名前のvolumeが作られます
docker volume create volume-test
volumeの詳細を見てみます
docker volume inspect volume-test
>>>[
>>> {
>>> "CreatedAt": "2022-12-06T16:53:56Z",
>>> "Driver": "local",
>>> "Labels": {},
>>> "Mountpoint": "/var/lib/docker/volumes/volume-test/_data",
>>> "Name": "volume-name",
>>> "Options": {},
>>> "Scope": "local"
>>> }
>>>]
Mountpointというものがこのホストシステム上のどこにvolume内のデータが保存されているかを示しています
今回の場合は/var/lib/docker/volumes/volume-test/_data
にデータが存在することが分かります
今作ったvolumeをコンテナに提供してみましょう
docker container run -itd \
--name volume-test \
--mount type=volume,src=/app \
ubuntu:22.04 /bin/bash
これでvolumeを持ったコンテナが作成され、バックグラウンドで起動しています
実際にvolumeにデータを保存してみます
docker container exec -it volume-test \
bash -c "echo 'Hello, World!' > /app/test.txt"
保存したデータをホストマシン上から確認します
ls /var/lib/docker/volumes/volume-test/_data
>>> test.txt
cat /var/lib/docker/volumes/volume-test/_data/test.txt
>>> Hello, World!
しっかりとホストマシンに保存されているのを確認できました!
このように、volumesはホストマシンのDockerが管理している部分にファイル・ディレクトリを保存します
Bind mount
次にbind mountの詳細を見ていきます一番の特徴はvolumesと違ってDockerに管理されていない好きなファイルやディレクトリをコンテナ内に提供できるところです
しかし、Dockerに管理されていないデータのためvolumesと比べるとDocker CLIのコマンドを利用できないなど、機能は限定されます
また、ホストマシンのファイルシステムに依存するため、ディレクトリ構造に依存します
Dockerの公式ドキュメントによるとvolumesの利用を推奨しているようです
実際にbind mount利用したコンテナを作成してみましょう
今回はあらかじめホストマシンにtest.txt
というファイルを作成しておき、それをコンテナからマウントします
echo "Hello, World!" > test.txt"
docker container run -it \
--name bind-test \
--mount type=bind,src="$(pwd)"/test.txt,dst=/app/test.txt \
ubuntu:22.04 /bin/bash
実際にコンテナ内にマウントされたか確認します
ls /app
>>> test.txt
cat /app/test.txt
>>> Hello, World!
ありました
次に、コンテナ内からこのファイルを書き替えてみます
echo "Bind mount test" > /app/test.txt
ホストマシン上から書き替わったか確認します
cat test.txt
>>> Bind mount test
このようにbind mountを使うとホストマシンの好きなファイル・ディレクトリとコンテナをつなげることができるようになります
tmpfs mount
tmpfs mountは他の2つと違って一時的なものでコンテナが停止するとメモリ上から削除されてしまいます
また、volumesやbind mountと違ってコンテナ間でデータを共有することもできません
他の2つと同じようにtmpfs mountも利用してみます
docker container run -it \
--name tmpfs-test \
--mount type=tmpfs,dst=/app \
ubuntu:22.04 /bin/bash
--mount
のオプションにtmpfs-mode
を追加すると権限を設定することができます
また、tmpfs-size
オプションでマウントサイズもバイト単位で指定可能です
それぞれ何に使うか
Volumes、Bind mount、tmpfs mountの簡単な詳細と使い方を紹介しました
次にどういうパターンのときにどのマウントを使えばいいのかを解説します
Volumes
基本的にはこれを利用するようにします
Dockerの管理下にvolumeが作成され、他のプロセスから触ることができないため安全です
利用例としてはアプリケーション開発で使用するデータベースのデータの保存などがあげられると思います
Bind mount
ホストマシン上で変更したソースコードをコンテナを止めずに反映したい場合やホスト側からデータを入れたい場合などに利用できます
tmpfs mount
tmpfs mountのデータはコンテナが停止した際にすべて削除されるため、image上に残って欲しくない機密情報や一時データ等の不要なデータを入れておくのに利用できます
まとめ
今回はコンテナ内のデータのマウント方法としてVolumes・Bind mount・tmpfs mountの3つを紹介しました
どれを使用するかはケースバイケースなので目的に合ったものを利用してください