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

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中。)


当前回答

你也可以放弃Dockerfile,因为它很简单,只需要使用一个基本的图像,并在你的compose文件中指定命令:

version: '3.2'

services:
  frontend:
    image: node:12-alpine
    volumes:
      - ./frontend/:/app/
    command: sh -c "cd /app/ && yarn && yarn run start"
    expose: [8080]
    ports:
      - 8080:4200

这对我来说特别有用,因为我只需要图像的环境,但在容器之外操作我的文件,我认为这也是您想要做的。

其他回答

我尝试了这个页面上最流行的答案,但遇到了一个问题:我的Docker实例中的node_modules目录会被缓存在命名或未命名的挂载点中,然后会覆盖作为Docker构建过程一部分构建的node_modules目录。因此,我将新模块添加到包中。json不会出现在Docker实例中。

幸运的是,我找到了这个很棒的页面,它解释了发生了什么,并提供了至少3种方法来解决它: https://burnedikt.com/dockerized-node-development-and-mounting-node-volumes/

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

有一个优雅的解决方案:

仅挂载应用程序目录,而不是整个目录。这样你就不会遇到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

在我看来,我们不应该在Dockerfile中运行npm install。相反,我们可以在运行正式的节点服务之前使用bash启动容器来安装依赖项

docker run -it -v ./app:/usr/src/app  your_node_image_name  /bin/bash
root@247543a930d6:/usr/src/app# npm install

我最近也遇到了类似的问题。可以在其他地方安装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