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

Web / -在端口5000上持有并运行一个python3 flask Web服务器。使用sqlite3。 Worker / -有一个index.js文件,它是队列的Worker。web服务器通过9730端口使用json API与这个队列进行交互。worker使用redis进行存储。worker还将数据存储在本地的worker/images/文件夹中

现在这个问题只与工人有关。

工人/ 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中。)


当前回答

使用Yarn,您可以通过设置将node_modules移到卷之外

# ./.yarnrc
--modules-folder /opt/myproject/node_modules

参见https://www.caxy.com/blog/how-set-custom-location-nodemodules-path-yarn

其他回答

你可以将node_modules移动到/文件夹中。

它是如何工作的

FROM node:0.12

WORKDIR /worker

COPY package.json /worker/
RUN npm install \
  && mv node_modules /node_modules

COPY . /worker/

你可以在Dockerfile中尝试这样做:

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

然后你应该像这样使用音量:

volumes:
  - worker/:/worker:rw

启动脚本应该是你的工作库的一部分,看起来像这样:

#!/bin/sh
npm install
npm start

因此,node_modules是你的工作卷的一部分,并被同步,当一切就绪时,npm脚本将被执行。

对于节点开发环境,我看到了两个不同的需求……将源代码挂载到容器中,并从容器中挂载node_modules(用于IDE)。要完成第一个,你需要做常规的坐骑,但不是所有的坐骑……正是你需要的东西

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

(不使用- /worker/node_modules的原因是,docker-compose会在运行之间持久化该卷,这意味着您可能会偏离映像中的实际内容(违背了不仅从主机绑定挂载的目的))。

第二题实际上更难。我的解决方案有点生硬,但很有效。我有一个脚本安装node_modules文件夹在我的主机上,我只需要记得调用它每当我更新包。Json(或者,将其添加到本地运行docker-compose build的make目标中)。

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

由于Node.js加载模块的方式,node_modules可以位于源代码路径中的任何位置。例如,将源代码放在/worker/src和包。Json在/worker中,所以/worker/node_modules是它们被安装的地方。

使用Yarn,您可以通过设置将node_modules移到卷之外

# ./.yarnrc
--modules-folder /opt/myproject/node_modules

参见https://www.caxy.com/blog/how-set-custom-location-nodemodules-path-yarn