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

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


当前回答

如果你不使用docker-compose,你可以这样做:

FROM node:10

WORKDIR /usr/src/app

RUN npm install -g @angular/cli

COPY package.json ./
RUN npm install

EXPOSE 5000

CMD ng serve --port 5000 --host 0.0.0.0

然后构建docker build -t myname。docker运行——rm -it -p 5000:5000 -v "$PWD":/usr/src/app/ -v /usr/src/app/node_modules myname

其他回答

如果你不使用docker-compose,你可以这样做:

FROM node:10

WORKDIR /usr/src/app

RUN npm install -g @angular/cli

COPY package.json ./
RUN npm install

EXPOSE 5000

CMD ng serve --port 5000 --host 0.0.0.0

然后构建docker build -t myname。docker运行——rm -it -p 5000:5000 -v "$PWD":/usr/src/app/ -v /usr/src/app/node_modules myname

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

如果希望node_modules文件夹在开发期间对主机可用,可以在启动容器时安装依赖项,而不是在构建时安装。我这样做是为了让语法高亮显示在编辑器中工作。

Dockerfile

# We're using a multi-stage build so that we can install dependencies during build-time only for production.

# dev-stage
FROM node:14-alpine AS dev-stage
WORKDIR /usr/src/app
COPY package.json ./
COPY . .
# `yarn install` will run every time we start the container. We're using yarn because it's much faster than npm when there's nothing new to install
CMD ["sh", "-c", "yarn install && yarn run start"]

# production-stage
FROM node:14-alpine AS production-stage
WORKDIR /usr/src/app
COPY package.json ./
RUN yarn install
COPY . .

dockerignore。

将node_modules添加到.dockerignore中,以防止Dockerfile运行COPY时复制node_modules。我们使用卷引入node_modules。

**/node_modules

docker-compose.yml

node_app:
    container_name: node_app
    build:
        context: ./node_app
        target: dev-stage # `production-stage` for production
    volumes:
        # For development:
        #   If node_modules already exists on the host, they will be copied
        #   into the container here. Since `yarn install` runs after the
        #   container starts, this volume won't override the node_modules.
        - ./node_app:/usr/src/app
        # For production:
        #   
        - ./node_app:/usr/src/app
        - /usr/src/app/node_modules

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

@FrederikNS提供的解决方案是可行的,但我更喜欢显式地命名我的node_modules卷。

我的项目/ docker-compose。Yml文件(docker-compose version 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

它创建了一个名为project_node_modules的卷,并在每次启动应用程序时重用它。

我的docker卷ls是这样的:

DRIVER              VOLUME NAME
local               project_mysql
local               project_node_modules
local               project2_postgresql
local               project2_node_modules