2016/11/17

docker-composeのvolumesで指定したホストのディレクトリがマウントされずハマった

Dockerで複数のコンテナを一度に扱いたいときに便利なツール「docker-compose」を使ったとき、volumesで指定したホストのディレクトリがマウントされずにハマった。

結果からいうと、マウントされるタイミングを勘違いしていたという話。

対処法についても一緒にまとめる。



ホストのディレクトリがマウントされない


以下のような構成で開発していた。
.
├── docker 
│   ├── docker-compose.yml
│   ├── nginx
│   │   ├── Dockerfile
│   │   └── app.conf
│   └── node
│       └── app.conf
├── web
│   ├── package.json
│   └── いろんなファイル
└── server
    ├── package.json
    └── いろんなファイル

./docker/docker-compose.yml
nginx:
  build: nginx
  volumes:
    - ../web:/root/www
  ports:
    - "80:80"
    - "443:443"
node:
  build: node
  volumes:
    - ../server:/root/server
  ports:
    - "3000:3000"

./docker/nginx/Dockerfile
FROM nginx

MAINTAINER BcRikko

ADD ./app.conf /etc/nginx/conf.d/app.conf

WORKDIR /root/www
RUN npm install    // <-- ここでエラー

EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]

./docker/node/Dockerfile
FROM node

MAINTAINER BcRikko

WORKDIR /root/server
RUN npm install    // <-- ここでエラー

ENV NODE_ENV production
CMD ["node", "app.js"]

どちらもRUN npm installをしようとするとエラーになってしまう。
docker-compose.ymlでvolumesを指定しているのに、なぜかマウントしたはずのpackage.jsonが見つからないようだ。

これでかなりの時間を費やしてしまった。



原因: docker-composeのvolumesとDockerfileのADDを同じと勘違いしていた



以下のようなDockerfileをビルドするときは、エラーにならない。
FROM  nginx

MAINTAINER BcRikko

ADD ./web /root/web

WORKDIR /root/web

RUN npm install  // <-- これは正常に動作する

EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]

ADDはDockerイメージをビルドする時点で、ホストのディレクトリがコンテナに追加されるので、/root/web/package.jsonを参照できnpm installが正常に実行できる。

しかし、docker-composeのvolumesは、docker run -v ./host/path:/container/path my_imageと同じ。ADDと大きく違う点は、コンテナが起動したときにマウントされるということだ。
そのため、DockerfileでDockerイメージをつくろうとした時点では、ホストのディレクトリがコンテナにマウントされておらず、package,jsonのファイルを参照できないため、エラーになってしまう。



対処方法


今回の件の対処法として、2つほど考えられる。
他にもありましたら、コメント等で教えていただけると助かります。

対処1. あらかじめnpm installする

1つめのDockerfile内にRUN npm installを書かずに、docker-compose up -dをする前に、ホスト環境でnpm installし、それをまるごとマウントする方法
ただしホスト環境にnode_modulesなど、ゴミが残ってしまうのが残念。


対処2. ホストのディレクトリ構成をかえる

2つめは、DockerイメージをつくるときにRUN npm installする方法
Dockerfileは、カレントディレクトリより上(親)の階層のディレクトリ/ファイルを参照することができないため、以下のようなディレクトリ構成にする。

.
├── docker-compose.yml
└── docker 
    ├── nginx
    │   ├── Dockerfile
    │   ├── app.conf
    │   └── web
    │       ├── package.json
    │       └── いろんなファイル
    └── node
        ├── app.conf
        └── server
            ├── package.json
            └── いろんなファイル

そして、Dockerfileも以下のように書き換える。
※docker-compose.ymlのvolumesの指定は不要
FROM nginx

MAINTAINER BcRikko

ADD ./app.conf /etc/nginx/conf.d/app.conf
ADD ./web /root/www

WORKDIR /root/www
RUN npm install

EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]

FROM node

MAINTAINER BcRikko

ADD ./server /root/server

WORKDIR /root/server
RUN npm install

ENV NODE_ENV production
CMD ["node", "app.js"]




以上

written by @bc_rikko

0 件のコメント :

コメントを投稿