Memento memo.

Today I Learned.

Docker と node_modules と Volume Trick

Rails & Node.jsの構成で Docker環境を作ろうとしたらハマったのでメモ

現象

npm installを実行する Dockerfileを記述

...
RUN mkdir /app
WORKDIR /app
# npm install
ADD package.json /app/package.json
RUN npm install
...

カレントディレクトリを /app にマウントするdocker-compose.ymlを記述

version: "2"

# これは失敗
services:
  web:
    build: .
    command: bundle exec rails server -p 3000 -b '0.0.0.0'
    ports:
      - "3000:3000"
    working_dir: /app
    volumes:
      - .:/app

するとnode_modulesが消える

原因

考えてみれば当たり前なんですが、
「node_modulesが出力されたコンテナ内のワーキングディレクトリに対して、ローカルのカレントディレクトリをマウントしてしまっている 」ため、コンテナ内のnode_modulesが隠れてしまいます。

解決策

こちらに書いてありました。 volume trick と紹介されています。

jdlm.info

version: "2"

services:
  web:
    build: .
    command: bundle exec rails server -p 3000 -b '0.0.0.0'
    ports:
      - "3000:3000"
    working_dir: /app
    volumes:
      - .:/app
      - /app/node_modules # コンテナ内のnode_moduleをvolumesに登録

複数マウントの詳細な挙動は謎なんですが、マウントで隠されたくないものをvolumesに登録しておくとコンテナ内のものが読まれるようになるそうです。

ちなみにbundle installなどでも同様の問題が起き得ますが、bundlerの場合はinstall先を環境変数でワーキングディレクトリ以外のパスに逃がせるのでそっちの方が楽です。