在 Docker 容器中安装 node_modules 并与主机同步

新手上路,请多包涵

我在 Docker 容器中安装 node_modules 并将它们与主机同步时遇到问题。我的 Docker 版本是 18.03.1-ce, build 9ee9f40 而 Docker Compose 的版本是 1.21.2, build a133471

我的 docker-compose.yml 看起来像:

 # Frontend Container.
frontend:
  build: ./app/frontend
  volumes:
    - ./app/frontend:/usr/src/app
    - frontend-node-modules:/usr/src/app/node_modules
  ports:
    - 3000:3000
  environment:
    NODE_ENV: ${ENV}
  command: npm start

# Define all the external volumes.
volumes:
  frontend-node-modules: ~

我的 Dockerfile

 # Set the base image.
FROM node:10

# Create and define the working directory.
RUN mkdir /usr/src/app
WORKDIR /usr/src/app

# Install the application's dependencies.
COPY package.json ./
COPY package-lock.json ./
RUN npm install

许多博客文章和 Stack Overflow 的答案都描述了外部卷的技巧。比如 这个

该应用程序运行良好。源代码是同步的。热重载也很好用。

我唯一的问题是主机上的 node_modules 文件夹是空的。是否可以将 Docker 容器内的 node_modules 文件夹与主机同步?

我已经阅读了这些答案:

  1. node_modules 上的 docker-compose 卷但为空
  2. 在 Docker 中安装 npm 后访问 node_modules

不幸的是,他们对我帮助不大。我不喜欢 第一个,因为我不想在我的主机上运行 npm install 因为可能存在跨平台问题(例如主机是 Windows 或 Mac,Docker 容器是 Debian 8或 Ubuntu 16.04)。 第二个 对我也不好,因为我想在我的 --- 中运行 npm install Dockerfile 而不是在 Docker 容器启动后运行它。

另外,我发现 了这篇博文。作者试图解决我面临的同样问题。问题是 node_modules 不会同步,因为我们只是将它们从 Docker 容器复制到主机。

我希望 Docker 容器内的 node_modules 与主机同步。请考虑到我想要的:

  • 自动安装 node_modules 而不是手动安装
  • 在 Docker 容器而不是主机中安装 node_modules
  • node_modules 与主机同步(如果我在 Docker 容器内安装了一些新包,它应该自动与主机同步,无需任何手动操作)

我需要在主机上有 node_modules ,因为:

  • 当我需要时可以阅读源代码
  • the IDE needs node_modules to be installed locally so that it could have access to the devDependencies such as eslint or prettier .我不想在全球范围内安装这些 devDependencies

提前致谢。

原文由 Vladyslav Turak 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.8k
2 个回答

首先,我要感谢 David Mazetrust512 发布他们的答案。不幸的是,他们没有帮助我解决我的问题。

我想发表我对这个问题的回答。

我的 docker-compose.yml

 ---
# Define Docker Compose version.
version: "3"

# Define all the containers.
services:
  # Frontend Container.
  frontend:
    build: ./app/frontend
    volumes:
      - ./app/frontend:/usr/src/app
    ports:
     - 3000:3000
    environment:
      NODE_ENV: development
    command: /usr/src/app/entrypoint.sh

我的 Dockerfile

 # Set the base image.
FROM node:10

# Create and define the node_modules's cache directory.
RUN mkdir /usr/src/cache
WORKDIR /usr/src/cache

# Install the application's dependencies into the node_modules's cache directory.
COPY package.json ./
COPY package-lock.json ./
RUN npm install

# Create and define the application's working directory.
RUN mkdir /usr/src/app
WORKDIR /usr/src/app

最后但并非最不重要 entrypoint.sh

 #!/bin/bash

cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/
exec npm start

The trickiest part here is to install the node_modules into the node_module ’s cache directory ( /usr/src/cache ) which is defined in our Dockerfile . After that, entrypoint.sh will move the node_modules from the cache directory ( /usr/src/cache ) to our application directory ( /usr/src/app ).由于这一点,整个 node_modules 目录将出现在我们的主机上。

看看我上面的问题,我想要:

  • 安装 node_modules 自动而不是手动
  • 在 Docker 容器而不是主机中安装 node_modules
  • node_modules 与主机同步(如果我在 Docker 容器内安装了一些新包,它应该自动与主机同步,无需任何手动操作

第一件事:自动安装 node_modules 。第二件事也完成了: node_modules 安装在 Docker 容器内(因此,不会有跨平台问题)。第三件事也完成了:安装在 Docker 容器内的 node_modules 将在我们的主机上 可见 并且它们将被 同步!如果我们在 Docker 容器中安装一些新包,它将立即与我们的主机同步。

需要注意的重要一点:说真的,安装在 Docker 容器中的新包会出现在 /usr/src/app/node_modules 中。由于这个目录与我们的主机同步,这个新包也会出现在我们主机的 node_modules 目录中。但是 /usr/src/cache/node_modules 将具有旧版本(没有这个新包)。无论如何,这对我们来说不是问题。 During next docker-compose up --build ( --build is required) the Docker will re-install the node_modules (because package.json was changed) and the entrypoint.sh 文件会将它们移动到我们的 /usr/src/app/node_modules

你应该考虑一件更重要的事情。如果你 git pull 来自远程存储库的代码或 git checkout your-teammate-branch 当Docker运行时,可能有一些新的包被添加到 package.json 文件中。在这种情况下,您应该使用 CTRL + C 停止 Docker,然后使用 docker-compose up --build 再次启动它(需要 --build )。如果您的容器作为守护进程运行,您应该只执行 docker-compose stop 来停止容器并使用 docker-compose up --build 再次启动它(需要 --build )。

如果您有任何问题,请在评论中告诉我。

希望这可以帮助。

原文由 Vladyslav Turak 发布,翻译遵循 CC BY-SA 4.0 许可协议

遇到这个问题并找到接受的答案非常慢,将所有 node_modules 复制到每个容器运行中的主机,我设法通过在容器中安装依赖项来解决它,镜像主机卷,然后跳过如果存在 node_modules 文件夹,则再次安装:

Dockerfile:

 FROM node:12-alpine

WORKDIR /usr/src/app

CMD [ -d "node_modules" ] && npm run start || npm ci && npm run start

码头工人-compose.yml:

 version: '3.8'

services:
  service-1:
    build: ./
    volumes:
      - ./:/usr/src/app

当您需要重新安装依赖项时,只需删除 node_modules

原文由 lewislbr 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题