はじめに
ReactをDockerで使ってみようとした際に、Reactのアプリケーションディレクトリを丸ごとバインドマウントしたところ、コンテナ側でインストールしたnode_modulesがホスト側にもマウントされてしまう、という問題にぶち当たりました。
その解消方法として、volume trick
というものがあったので、少し試してみた記事になります。
volume trick とは
バインドマウントするフォルダ内にマウントさせたくないフォルダが存在する場合に、そのフォルダをマウント対象から除外する方法。
参考: https://jdlm.info/articles/2016/03/06/lessons-building-node-app-docker.html
※ Dockerfile内の COPY
や ADD
でコンテナ内にファイルを配置する場合は .dockerignore
が使えるので、わざわざ volume trick を使う必要はありません。(参考)
リポジトリ
ファイル構造
今回試してみた際のファイル構造は下記の通りです。
.
├── docker-compose.yml
├── Dockerfile
└── src
├── target
│ └── inHost.txt // コンテナ側にマウントされないことを確認したい
└── index.html
この構造で、src
はバインドマウントするが、src/target
はマウントしないようにします。
ファイル記述
FROM nginx:latest
WORKDIR /usr/share/nginx/html
RUN mkdir target \
&& echo touch in image > target/inImage.txt # ホスト側にマウントされないことを確認したい
version: "3.8"
services:
server:
build: .
ports:
- 80:80
volumes:
- ./src:/usr/share/nginx/html # バインドマウント
- exception-volumes:/usr/share/nginx/html/target # バインドマウントするフォルダ中のtargetフォルダのみvolumeマウントの対象とする
volumes:
exception-volumes: # volume trick用のダミーのvolume
動かしてみる
$ docker compose up -d --build
$ docker compose exec server ls
index.html target
$ docker compose exec server ls target
inImage.txt
$ ls src
index.html target
$ ls src/target
inHost.txt
動かしてみた結果、下記のことを確認することができました。
- ホスト側の
target/inHost.txt
がコンテナ側にない - イメージビルド時に作成した
target/inImage.txt
がコンテナ側にはあるが、ホスト側にはない
図で表すと下記のような差分があります。
.
├── target
+ │ └── inImage.txt
- │ └── inHost.txt
└── index.html
コンテナとボリュームのイメージとしては、下記になります。
(こちらのページのイメージ図がわかりやすかったので、参考にしています。)
+--<Host>--+ +--<Docker>-----------------------------------------------------------------+
| | | +--<Container:c1>-------------------+ +--<Volume:exception-volumes>--+ |
| | | | | | | |
| ./src/------------> /usr/share/nginx/html | | | |
| | | | /usr/share/nginx/html/target <---------/ | |
| | | | | | | |
| | | +-----------------------------------+ +------------------------------+ |
+----------+ +---------------------------------------------------------------------------+
結果
対象のフォルダをバインド対象から外すことができました!