ストレージ@Docker¶
はじめに¶
本サイトにつきまして、以下をご認識のほど宜しくお願いいたします。
01. Docker マウント¶
Docker マウントとは¶
コンテナのファイルデータをホストのストレージに一時化/非永続化/永続化するための方法である。

02. バインドマウント¶
バインドマウントとは¶
ホスト側のストレージ上のディレクトリを、コンテナ側にマウントすることで、データを永続化する。
ホストで作成されるデータが継続的に変化する場合に適しており、例えば開発環境でアプリケーションをホストコンテナ間と共有する方法として推奨である。
しかし、ホスト側のデータを永続化する方法には適さない。

使用方法¶
docker コマンド、docker-compose.yml ファイル、で定義できる。
なお、バインドマウントは Dockerfile では定義できない。
*例*
# ホストをコンテナ側にバインドマウント
$ docker run -d -it --name <コンテナ名> /bin/bash \
--mount type=bind, src=home/projects/<ホスト側のディレクトリ名>, dst=/var/www/<コンテナ側のディレクトリ名>
version: "3.9"
services:
nextjs:
ports:
- 3000:3000
build:
context: .
dockerfile: Dockerfile
container_name: hr_website_container
volumes:
- ./app:/usr/src/app
マウント元として指定できるディレクトリ¶
以下の通り、ホスト側のマウント元のディレクトリにはいくつか選択肢がある。
Docker for Desktop の設定画面で変更する。

マウント元の詳細なディレクトリ名は、/Users/<ユーザー名>/Library/Group Containers/group.com.docker/setting.json ファイルから確認できる。
$ cat settings.json
{
...
"dataFolder": "/Users/<ユーザー名>/Library/Containers/com.docker.docker/Data/vms/0/data",
...
"filesharingDirectories": [
"/tmp",
"/Users",
"/Volumes",
"/private"
],
...
}
03. ボリュームマウント¶
ボリュームマウントとは¶
ホスト側のストレージ上にある docker エリア (/var/lib/docker/volumes ディレクトリ) のマウントポイント (/var/lib/docker/volumes/<ボリューム名>/_data) を、コンテナ側にマウントすることで、データを永続化する。
ホストで作成されるデータをめったに変更しない場合に適しており、例えば DB レコードをホストコンテナ間と共有する方法として推奨である。
しかし、例えばアプリケーションやパッケージのような変更されやすいデータを共有する方法には適さない。

ボリューム、マウントポイントとは¶
docker エリア (/var/lib/docker/volumes ディレクトリ) に保管される永続データをボリュームという。
また、デバイスファイルに紐づくディレクトリ (/var/lib/docker/volumes/<ボリューム名>/_data) をマウントポイントといい、マウントポイントに対してマウント処理が必要である。
使用方法¶
docker コマンドの実行、Dockerfile、docker-compose.yml ファイル、で定義できる。
*例*
# ホストをコンテナ側にバインドマウント
$ docker run -d -it --name <コンテナ名> /bin/bash \
--mount type=volume, src=home/projects/<ホスト側のディレクトリ名>, dst=/var/www/<コンテナ側のディレクトリ名>
FROM ubuntu:latest
RUN mkdir /data
WORKDIR /data
RUN echo "Hello from Volume" > test
VOLUME /data
version: "3.9"
services:
nextjs:
ports:
- 3000:3000
build:
context: .
dockerfile: Dockerfile
container_name: hr_website_container
volumes:
# ボリュームマウント
- /usr/src/app/node_modules
- /usr/src/app/.next
Data Volume コンテナによる永続データの提供¶
ボリュームを使用する場合のコンテナ配置手法の一種。
docker エリアのボリュームを Data Volume をコンテナのディレクトリにマウントしておく。
ボリュームを使用するときは、docker エリアを参照するのではなく、Data Volume コンテナを参照する。

04. tmpfs マウント¶
tmpfs マウントとは¶
Docker on Linux のみで使用できる。
ホスト側のメモリ上にあるディレクトリを、コンテナ側にマウントすることで、データを非永続化する。
コンテナが停止すると、tmpfs マウントは終了し、ディレクトリは削除される。
05. バインドマウント、ボリュームマウント、COPY 処理、NFS¶
脆弱性の比較¶
本番環境で、ホストからコンテナにバインドマウントを実行できる。
しかしバインドマウントでは、ホスト側のコードが隔離されておらず、コンテナ側のコードからホスト側の関係ないファイルへもアクセスできてしまう。
例えば cd コマンドによって、ホスト側のマウントと関係ないディレクトリにアクセスできてしまう。
一方でボリュームマウント (VOLUME 処理) では、ホスト側のコードは docker エリア内に隔離されており、ホストのほかのファイルからは切り離されている。
これにより、マウントに関係のないファイルへはアクセスできないようになっている。
そのため、バインドマウントより安全である。
本番環境での使いやすさの比較¶
脆弱性の観点から、本番環境ではボリュームマウント (VOLUME 処理) や COPY 処理を使用し、アプリケーションをコンテナイメージへ組み込む。
そのうえで、ボリュームマウントでは、組み込んだアプリケーションのコードをコンテナ起動後しか参照できないため、コードの組み込みとコンテナ起動の間にアプリケーションを加工する (例:ディレクトリの実行権限を変更するなど) 場合は COPY 処理のほうが便利である。
方法として、コンテナイメージレジストリ内のプライベートリポジトリにデプロイするイメージのビルド時に、ホスト側のアプリケーションをイメージ側に COPY 処理しておく。
これにより、本番環境ではこのコンテナイメージをプルしさえすれば、アプリケーションを使用できるようになる。
性能の比較¶
アプリケーションが処理を実行するとき、多くのパッケージが読み出される。
このとき、ホスト上で稼働するコンテナの性能は、『COPY、NFS > ボリュームマウント > バインドマウント』の順で高い。
| バインドマウント | ボリュームマウント | COPY 処理 |
NFS | |
|---|---|---|---|---|
| 性能に関する説明 | バインドマウントでは、ホストとコンテナ間のライフサイクルは同じであり、ファイルの状態が同期されている。このとき、コンテナからホストにアウトプット処理、またホストからコンテナにインプット処理が発生する。そのため、コンテナではアプリケーションの処理を実行しながら、合わせてホスト間と I/O 処理も実行することになり、コンテナの性能は悪い。 | ボリュームマウントでは、ホストとコンテナ間のライフサイクルは分離されており、ファイルの状態は同期されていない。そのため、ボリュームマウントよりはコンテナの性能がよい。 | COPY 処理では、コンテナイメージのビルド時にコードを組み込むのみで、以降、ホストとコンテナ間でコードの I/O 処理は発生しない。そのため、バインドマウントやボリュームマウントと比べて、コンテナの性能がよい。このことは、Docker のみでなく Kubernetes でも同様である。 |
NFS を使用したマウントでは、高速で I/O 処理が実行される。そのため、コンテナの性能がよい。 |
| 補足 | ・https://stackoverflow.com/questions/64629569/docker-bind-mount-directory-vs-named-volume-performance-comparison ・https://qiita.com/ucan-lab/items/a88e2e5c2a79f2426163 |
•https://qiita.com/ucan-lab/items/a88e2e5c2a79f2426163 | •https://qiita.com/kunit/items/36d9e5fa710ad26f8010 |