[Dd]enzow(ill)? with DB and Python

DBとか資格とかPythonとかの話をつらつらと

Dockerで特定のサブディレクトリだけホストと共有しない( Data Volume)

現在の仕事では各個人の開発環境を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 Volumewebpackコンテナの/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周りを少し調べました。まだ雰囲気でやっているところが多いですが引き続き使いながら覚えていこうと思います。