javascript - 容器与宿主机共享 `node_modules`文件夹

标签 javascript node.js docker docker-compose docker-machine

这是一个非常热门的话题,但我从未真正找到解决方案。

您可能知道,当我们在容器中有一个卷并且我们从 Dockerfile(具有默认权限)安装依赖项(使用 npm i 或其他东西)时,Npm 将创建一个 node_modules容器中的文件夹 root:root访问权限。

我在使用此方法时遇到了两个问题(在本地/开发环境中):

  1. node_modules文件夹仅存在于容器内,但主机的 IDE/LSP 需要此文件夹才能正常工作(模块导入、类型定义等)。

  2. 如果宿主想要安装/更新一个包(npm i ... 等),他将不得不重新启动并为node_modules 重建容器。要更新的文件夹。

所以我想到了另一个想法,如果我使用 CMD 安装依赖项会怎么样?在 Dockerfile 中(或 command 文件中服务的 docker-compose 属性)并使用卷,因此 node_modules可以分享给楼主。不幸的是,这种方法引入了新问题。例如,node_modules有一个 root:root权限访问,所以如果您的主机的用户名是“命名”的,并且没有相同的 uid & gid您将需要运行 root 访问命令更新 node_modules (sudo npm i ...)。

这是我当前的配置:

docker-compose.yml :

version: '3.7'

services:
  app:
    container_name: 'app_DEV'
    build: .
    command: sh -c "yarn install && node ./server.js"
    volumes:
      - ./:/usr/src/app
    ports:
      - 3000:3000
    tty: true

Dockerfile :

FROM node:12.8.1-alpine

WORKDIR /usr/src/app

COPY . .

package.json :

{
  "dependencies": {
    "express": "^4.17.1"
  }
}

server.js :

const app = require('express')();

app.get('/', (req, res) => {
  res.send('Hello');
});

app.listen(3000, () => console.log('App is listening on port 3000'));

然后你可以尝试运行docker-compose up并做一个 ls -la :

-rw-r--r--  1 mint mint   215 août  23 16:39 docker-compose.yml
-rw-r--r--  1 mint mint    56 août  23 16:29 Dockerfile
drwxr-xr-x 52 root root  4096 août  23 16:31 node_modules
-rw-r--r--  1 mint mint    53 août  23 16:31 package.json
-rw-r--r--  1 mint mint   160 août  23 16:29 server.js

如您所见,每个文件/文件夹都有 mint:mint访问 node_modules 除外(mint 是我的主机的用户)。

总结一下我的问题:有没有更好的方法来管理 Docker 容器对 NodeJS 的依赖性?

最佳答案

一般来说,我不会推荐这种方法,因为您的主机和容器可能无法共享相同的模块。例如,如果您团队中的其他人使用 Windows 并且您有一些已编译的模块(即 node-sass 或 bcrypt),共享这些模块会使容器或主机无法使用它们。

另一种经常出现的解决方案是在 Dockerfile 中分离 node_modules 安装步骤,并为此覆盖卷安装。每次要添加包时,您仍然需要重建 Docker 镜像,但这(可能)不应该经常发生。

这是 Dockerfile 的相关部分:

FROM node:12.8.1-alpine

WORKDIR /usr/src/app

COPY ./package*.json .
COPY ./yarn.lock .

RUN yarn

COPY . .

CMD [ "yarn", "start" ]

然后,在您的 docker-compose 文件中:

version: '3.7'

services:
  app:
    container_name: 'app_DEV'
    build: .
    command: sh -c "yarn install && node ./server.js"
    volumes:
      - ./:/usr/src/app
      - /usr/src/app/node_modules/
    ports:
      - 3000:3000
    tty: true

确保将 /usr/src/app/node_modules/AFTER 包含在根装载中,因为它将在容器中覆盖它。此外,结尾的斜杠很重要。

关于javascript - 容器与宿主机共享 `node_modules`文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57628844/

相关文章:

javascript - 函数如何获取 'x' 值

javascript - 将 vuejs 函数绑定(bind)为上下文 vuejs 的数据

javascript - 如何将物理添加到 CSS 动画中?

javascript - 使用 Cheerio 对象制作 For 循环的正确方法是什么?

node.js - 无法使用 Node 运行服务器

node.js - 如何为自己的 npm 包创建自定义 cli 命令

amazon-web-services - EBS 卷显示没有挂载点

docker - 如何在不重建镜像的情况下修改docker健康检查?

docker - containerd.io 与 docker-ce-cli 与 docker-ce : what are the differences and what does each package do?

c# - 使用值从 .net 代码隐藏调用 javascript 函数