245

次のサービスを備えたアプリがあります。

  • web/- ポート 5000 で Python 3 フラスコ Web サーバーを保持して実行します。sqlite3 を使用します。
  • worker/-index.jsキューのワーカーであるファイルがあります。Web サーバーは、ポート経由で json API を使用してこのキューと対話します9730。ワーカーはストレージに redis を使用します。ワーカーはデータをローカルのフォルダーにも保存しますworker/images/

現在、この質問はworker.

worker/Dockerfile

FROM node:0.12

WORKDIR /worker

COPY package.json /worker/
RUN npm install

COPY . /worker/

docker-compose.yml

redis:
    image: redis
worker:
    build: ./worker
    command: npm start
    ports:
        - "9730:9730"
    volumes:
        - worker/:/worker/
    links:
        - redis

を実行するdocker-compose buildと、すべてが期待どおりに機能し、すべての npm モジュールが/worker/node_modules期待どおりにインストールされます。

npm WARN package.json unfold@1.0.0 No README data

> phantomjs@1.9.2-6 install /worker/node_modules/pageres/node_modules/screenshot-stream/node_modules/phantom-bridge/node_modules/phantomjs
> node install.js

<snip>

しかし、そうするとdocker-compose up、次のエラーが表示されます。

worker_1 | Error: Cannot find module 'async'
worker_1 |     at Function.Module._resolveFilename (module.js:336:15)
worker_1 |     at Function.Module._load (module.js:278:25)
worker_1 |     at Module.require (module.js:365:17)
worker_1 |     at require (module.js:384:17)
worker_1 |     at Object.<anonymous> (/worker/index.js:1:75)
worker_1 |     at Module._compile (module.js:460:26)
worker_1 |     at Object.Module._extensions..js (module.js:478:10)
worker_1 |     at Module.load (module.js:355:32)
worker_1 |     at Function.Module._load (module.js:310:12)
worker_1 |     at Function.Module.runMain (module.js:501:10)

/worker/node_modules(ホスト上またはコンテナ内に)モジュールが存在しないことが判明しました。

ホストが I のnpm install場合、すべて正常に動作します。しかし、私はそれをしたくありません。コンテナーで依存関係を処理する必要があります。

ここで何がうまくいかないのですか?

(言うまでもなく、すべてのパッケージは にありpackage.jsonます。)

4

18 に答える 18

371

これは、ビルド中にボリュームがマウントされていないため、workerディレクトリを にボリュームとして追加したために発生します。docker-compose.yml

docker がイメージをビルドすると、node_modulesディレクトリ内にディレクトリが作成され、workerすべての依存関係がそこにインストールされます。次に、実行時に、workerdocker の外部からのディレクトリが docker インスタンス (インストールされていない) にマウントされ、インストールしたばかりのものがnode_modules隠されます。node_modulesこれは、マウントされたボリュームを から削除することで確認できますdocker-compose.yml

回避策は、データ ボリュームを使用してすべての を保存することです。データ ボリュームは、ディレクトリがマウントさnode_modulesれる前に、ビルドされた Docker イメージからデータをコピーするためです。workerこれは、次のdocker-compose.ymlように行うことができます。

redis:
    image: redis
worker:
    build: ./worker
    command: npm start
    ports:
        - "9730:9730"
    volumes:
        - ./worker/:/worker/
        - /worker/node_modules
    links:
        - redis

これがイメージの移植性に問題を引き起こすかどうかは完全にはわかりませんが、主に docker を使用してランタイム環境を提供しているように見えるので、これは問題にはなりません。

ボリュームについて詳しく知りたい場合は、https ://docs.docker.com/userguide/dockervolumes/ で利用できる優れたユーザー ガイドがあります。

編集: Docker はそれ以来./、 docker-compose.yml ファイルに関連するファイルにマウントするための先頭を必要とするように構文を変更しました。

于 2015-09-25T14:56:39.217 に答える
55

フォルダーはnode_modulesボリュームによって上書きされ、コンテナー内でアクセスできなくなります。ボリュームからフォルダーを取り出すために、ネイティブ モジュールの読み込み戦略を使用しています。

/data/node_modules/ # dependencies installed here
/data/app/ # code base

Dockerfile:

COPY package.json /data/
WORKDIR /data/
RUN npm install
ENV PATH /data/node_modules/.bin:$PATH

COPY . /data/app/
WORKDIR /data/app/

node_modulesディレクトリはイメージに含まれているため、コンテナーの外部からはアクセスできません。

于 2015-10-13T15:25:04.013 に答える
35

私は最近、同様の問題を抱えていました。他の場所にインストールして、環境変数node_modulesを設定できます。NODE_PATH

以下の例では、私はにインストールnode_modulesしました/install

ワーカー/Dockerfile

FROM node:0.12

RUN ["mkdir", "/install"]

ADD ["./package.json", "/install"]
WORKDIR /install
RUN npm install --verbose
ENV NODE_PATH=/install/node_modules

WORKDIR /worker

COPY . /worker/

docker-compose.yml

redis:
    image: redis
worker:
    build: ./worker
    command: npm start
    ports:
        - "9730:9730"
    volumes:
        - worker/:/worker/
    links:
        - redis
于 2016-02-10T14:09:13.973 に答える
22

エレガントなソリューションがあります:

ディレクトリ全体ではなく、アプリディレクトリのみをマウントするだけです。この方法で問題が発生することはありませんnpm_modules

例:

  frontend:
    build:
      context: ./ui_frontend
      dockerfile: Dockerfile.dev
    ports:
    - 3000:3000
    volumes:
    - ./ui_frontend/src:/frontend/src

Dockerfile.dev:

FROM node:7.2.0

#Show colors in docker terminal
ENV COMPOSE_HTTP_TIMEOUT=50000
ENV TERM="xterm-256color"

COPY . /frontend
WORKDIR /frontend
RUN npm install update
RUN npm install --global typescript
RUN npm install --global webpack
RUN npm install --global webpack-dev-server
RUN npm install --global karma protractor
RUN npm install
CMD npm run server:dev
于 2016-12-03T20:51:35.453 に答える
16

更新: @ FrederikNS が提供するソリューションを使用してください。

同じ問題が発生しました。フォルダー/workerがコンテナーにマウントされると、そのすべてのコンテンツが同期されます (そのため、ローカルにない場合、node_modules フォルダーは表示されなくなります)。

OS ベースの npm パッケージに互換性がないため、モジュールをローカルにインストールしてからコンテナーを起動することはできませんでした。

これに対する私の解決策は、ソースをフォルダーにラップしてから、この index.js ファイルを使用してそのフォルダーにsrcリンクすることでした。これで、ファイルがアプリケーションの開始点になりました。node_modulesindex.js

コンテナーを実行すると、/app/srcフォルダーがローカルsrcフォルダーにマウントされます。

したがって、コンテナー フォルダーは次のようになります。

/app
  /node_modules
  /src
    /node_modules -> ../node_modules
    /app.js
  /index.js

それは醜いですが、それは動作します..

于 2015-05-15T14:08:41.630 に答える
8

プロジェクトフォルダーとは異なるコンテナーにnode_modulesをインストールし、NODE_PATHをnode_modulesフォルダーに設定すると役立ちます(コンテナーを再構築する必要があります)。

docker-compose を使用しています。私のプロジェクトファイル構造:

-/myproject
--docker-compose.yml
--nodejs/
----Dockerfile

docker-compose.yml:

version: '2'
services:
  nodejs:
    image: myproject/nodejs
    build: ./nodejs/.
    volumes:
      - ./nodejs:/workdir
    ports:
      - "23005:3000"
    command: npm run server

nodejs フォルダー内の Dockerfile:

FROM node:argon
RUN mkdir /workdir
COPY ./package.json /workdir/.
RUN mkdir /data
RUN ln -s /workdir/package.json /data/.
WORKDIR /data
RUN npm install
ENV NODE_PATH /data/node_modules/
WORKDIR /workdir
于 2016-11-30T10:36:33.697 に答える
2

Dockerfile で次のようなことを試すことができます。

FROM node:0.12
WORKDIR /worker
CMD bash ./start.sh

次に、次のようにボリュームを使用する必要があります。

volumes:
  - worker/:/worker:rw

startscript はワーカー リポジトリの一部である必要があり、次のようになります。

#!/bin/sh
npm install
npm start

したがって、node_modules はワーカー ボリュームの一部であり、同期され、すべてが起動すると npm スクリプトが実行されます。

于 2019-03-21T13:36:24.877 に答える