採用はこちら!

Shinonome Tech Blog

株式会社Shinonomeの技術ブログ
3 min read

DockerのVolumes・Bind mount・tmpfs mountsの違いと使い方

Dockerでデータの永続化や別のコンテナへの移行、ホストマシンとの共有などをする際にvolumesやbind mount等を利用すると思いますが、今回はそれぞれの違いや使い方を勉強がてら書いていきます

こんにちは!サーバサイドを勉強中のこのぴーです
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つを紹介しました
どれを使用するかはケースバイケースなので目的に合ったものを利用してください