現在の仕事では各個人の開発環境をDockerで用意しています。基本的にコードがあるディレクトリをコンテナ側と共有していますが、一部分だけ共有したくないというケースが発生しました。以下のようなケースです。
drwxr-xr-x 571 denzow staff 19414 3 18 09:43 node_modules -rw-r--r-- 1 denzow staff 286 3 18 09:43 package.json drwxr-xr-x 3 denzow staff 102 3 18 09:47 src -rw-r--r-- 1 denzow staff 584 3 18 09:47 webpack.config.js -rw-r--r-- 1 denzow staff 134 3 18 09:51 Dockerfile_webpack -rw-r--r-- 1 denzow staff 205 3 18 09:52 docker-compose.yml
src配下のファイルをdistにビルドするwebpackを導入したコンテナを構成しています。このディレクトリをコンテナと共有しますが、ホスト側がMacでコンテナ内がLinuxですのでnode_modulesはできれば共有したくありません。カレントは共有する、ただしnode_modulesを除くという状況の実現方法を調べました。
本例詳細
関連ファイルの現時点での内容は以下です。
- Dockerfile_webpack
FROM node:7.1.0 WORKDIR /app COPY ./package.json package.json RUN npm install
- docker-compose.yml
version: '3.0' services: webpack: build: context: . dockerfile: Dockerfile_webpack restart: always command: 'node node_modules/.bin/webpack --watch' volumes: - .:/app
volumesの指定にあるように、ホスト側の.をコンテナ内の/appにマウントしています。ここから./node_modulesを除外していきます。 現時点では以下のように共有されてしまっています。
-- ホスト側でファイル作成 denzownoMacBook-Pro:submount denzow$ touch node_modules/test -- コンテナ側からもファイルが見えている denzownoMacBook-Pro:submount denzow$ docker exec submount_webpack_1 ls -l node_modules/test -rw-r--r-- 1 root root 0 Mar 18 01:08 node_modules/test
どうするのか
このStackoverflowが参考になりましした。
端的に言えば、volumeを作ってホスト側と共有したくないディレクトリに重ねるというものです。docker-compose.ymlを以下のように変更します。
version: '3.0'
services:
webpack:
build:
context: .
dockerfile: Dockerfile_webpack
restart: always
command: 'node node_modules/.bin/webpack --watch'
volumes:
- .:/app
+ - node_modules:/app/node_modules
+
+ volumes:
+ node_modules:
+ driver: 'local'
以下の部分でData Volumeを作成しています。
volumes: node_modules: driver: 'local'
そして、ここで作成したData Volumeをwebpackコンテナの/app/node_modulesにマウントしています。これでコンテナの/app/node_modulesはホストの<base_dir>/node_modulesと分けることができます。
実際に確認すると以下のように共有されていないことがわかります。
-- ホスト側でファイル作成 denzownoMacBook-Pro:submount denzow$ touch node_modules/test -- コンテナからは見えていない denzownoMacBook-Pro:submount denzow$ docker exec submount_webpack_1 ls -l node_modules/test ls: cannot access node_modules/test: No such file or directory
docker inspectでも別のディレクトリになっていることがわかります。
denzownoMacBook-Pro:submount denzow$ docker inspect submount_webpack_1
:
"Mounts": [
{
"Type": "bind",
"Source": "/Users/denzow/work/docker_test/submount",
"Destination": "/app",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "volume",
"Name": "submount_node_modules",
"Source": "/var/lib/docker/volumes/submount_node_modules/_data",
"Destination": "/app/node_modules",
"Driver": "local",
"Mode": "rw",
"RW": true,
"Propagation": ""
}
],
まぁ、Macなので/var/lib/docker/volumes/submount_node_modules/_dataはMac内の仮想環境(Docker.qcow2)に含まれており、ホスト側からも直接は参照できませんが…
コンテナ間の共有
さて、作ったnode_modulesボリュームコンテナは他のコンテナとも共有できます。
version: '3.0'
services:
webpack:
build:
context: .
dockerfile: Dockerfile_webpack
restart: always
command: 'node node_modules/.bin/webpack --watch'
volumes:
- .:/app
- node_modules:/app/node_modules
+ work:
+ image: ubuntu
+ restart: always
+ command: 'tail -f /dev/null'
+ volumes:
+ - node_modules:/test_node_modules
volumes:
node_modules:
driver: 'local'
新たにworkというコンテナを追加して、node_modulesを/test_node_modulesにマウントしています。この領域への操作がwebpackコンテナからもworkコンテナからも共有できるかを確認します。
-- workコンテナからファイルを作成 denzownoMacBook-Pro:submount denzow$ docker exec submount_work_1 touch /test_node_modules/from_worker -- webpackコンテナからも見えている denzownoMacBook-Pro:submount denzow$ docker exec submount_webpack_1 ls -l /app/node_modules/from_worker -rw-r--r-- 1 root root 0 Mar 18 01:38 /app/node_modules/from_worker
-- webpackコンテナからファイルを作成 denzownoMacBook-Pro:submount denzow$ docker exec submount_webpack_1 touch /app/node_modules/from_webpack -- workコンテナからも見えている denzownoMacBook-Pro:submount denzow$ docker exec submount_work_1 ls -l /test_node_modules/from_webpack -rw-r--r-- 1 root root 0 Mar 18 01:44 /test_node_modules/from_webpack
相互に作製したファイルが見えていることがわかります。
まとめ
dockerのData Volume周りを少し調べました。まだ雰囲気でやっているところが多いですが引き続き使いながら覚えていこうと思います。