【问题标题】:Install all needed node modules inside Docker container, not just copying them在 Docker 容器中安装所有需要的节点模块,而不仅仅是复制它们
【发布时间】:2021-04-11 13:25:10
【问题描述】:

问题如下。我们有一个项目,其中有几个使用 docker compose 运行的服务。 当我们中的一个人使用npm install <module name> --save 添加一个新模块时,package*.json 文件将被更新,并且该模块将被安装在 node_module 文件夹中。 在这里,运行docker-compose up --build 一切正常。 然而,当其他人拉取 package*.json 文件的更新版本并尝试运行docker-compose up --build 时,Docker 会输出找不到模块的错误。 好像本地的 node_module 文件夹直接复制到了 Docker 容器中。

问题是我们如何才能使 package*.json 文件中所有需要的节点模块都安装在容器中,而不仅仅是复制?

这是一个 DOCKERFILE:

FROM node:14

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD npm run devStart

以及 docker-compose.yaml 文件:

version: "3"
services:
  list-service:
    build:
      context: ./list-service
      dockerfile: Dockerfile
    ports:
      - "4041"
    volumes:
      - ./list_service:/usr/src/app
      #- /usr/src/app/node_modules
  
  user-service:
    build:
      context: ./user_service
      dockerfile: Dockerfile
    ports:
      - "4040"
    volumes:
      - ./user_service:/usr/src/app
     # - /usr/src/app/node_modules

  api-gateway:
    build:
      context: ./api_gateway
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    volumes:
      - ./api_gateway:/usr/src/app
     # - /usr/src/app/node_modules

  date_list-service:
    build:
      context: ./date_list_service
      dockerfile: Dockerfile
    ports:
     - "4042"
    volumes:
      - ./date_list_service:/usr/src/app
    #  - /usr/src/app/node_modules

  mongo:
    container_name: mongo
    image: mongo
    command: mongod --port 27018
    volumes:
      - data:/data/db
  
volumes:
  data:

我们确实已经有一个 .dockerignore 文件:

node_modules
npm-debug.log

更新

@DazWilkin 认识到我们将上下文挂载到容器中。这会用本地内容覆盖图像内容。我们这样做是因为我们使用 nodemon。因此,我们可以即时看到代码的变化。是否有可能从这里排除 node_modules 目录?

【问题讨论】:

    标签: node.js docker npm docker-compose node-modules


    【解决方案1】:

    我认为您的问题是 Docker 正在缓存层并且没有检测到更改的package*.json

    如果每个人都docker-compose up --build --no-cache 会发生什么?

    注意因为您在容器映像构建中运行npm install,所以您不需要(并且可能不希望)预先在主机上运行npm install

    注意 由于您使用的是容器,因此您可能还想使用容器注册表。这样,一旦构建了第一个更新的 docker 镜像,其他人就可以从注册表中提取这些镜像,而不是为自己重建它们。

    更新

    我刚刚注意到您将context 安装在容器中;你不想那样做。它将覆盖您构建容器所做的工作:

    version: "3"
    services:
      list-service:
        build:
          context: ./list-service
          dockerfile: Dockerfile
        ports:
          - "4041"
        volumes:
          - ./list_service:/usr/src/app <<< ---- DELETE
          #- /usr/src/app/node_modules
      
      user-service:
        build:
          context: ./user_service
          dockerfile: Dockerfile
        ports:
          - "4040"
        volumes:
          - ./user_service:/usr/src/app <<< ---- DELETE
         # - /usr/src/app/node_modules
    
      api-gateway:
        build:
          context: ./api_gateway
          dockerfile: Dockerfile
        ports:
          - "5000:5000"
        volumes:
          - ./api_gateway:/usr/src/app <<< ---- DELETE
         # - /usr/src/app/node_modules
    
      date_list-service:
        build:
          context: ./date_list_service
          dockerfile: Dockerfile
        ports:
         - "4042"
        volumes:
          - ./date_list_service:/usr/src/app <<< ---- DELETE
        #  - /usr/src/app/node_modules
    
      mongo:
        container_name: mongo
        image: mongo
        command: mongod --port 27018
        volumes:
          - data:/data/db
      
    volumes:
      data:
    

    【讨论】:

    • 即使我删除所有图像并运行docker-compose builddocker-compose build,也找不到该模块。有时我们在没有 docker 的情况下运行这些服务,所以我们需要本地的 node_modules。似乎 Docker 只是复制 node_modules 而不是安装它们。
    • 很好奇。问题出现在多台机器上还是只出现在一台机器上?
    • 哦,等一下...我现在看到您正在将 context 安装到容器中
    • 发生在多台机器上。
    • 我已经更新了我的答案......您不应该将上下文挂载到容器中。通过这样做,您将使用本地(主机)内容覆盖图像的内容。那不是你想做的。图像包含已构建到图像中的上下文的副本。您的图像是用例如构建的WORKDIR /usr/src/app 然后你例如用本地主机的内容覆盖它。不要那样做。
    猜你喜欢
    • 2016-06-07
    • 1970-01-01
    • 2015-12-20
    • 2016-09-06
    • 1970-01-01
    • 2022-01-09
    • 2016-02-15
    • 1970-01-01
    • 2021-04-17
    相关资源
    最近更新 更多