在容器和主机之间共享 `node_modules` 文件夹

Cra*_*zit 6 javascript node.js docker docker-compose docker-machine

这是一个非常讨论的话题,但我从未找到解决方案。

因此,您可能知道,当我的容器中有一个卷并且我yarn install使用 Dockerfile 中的 a安装我的依赖项时,Yarn 将node_modules在我的容器上创建一个具有root:root访问权限的文件夹。

这种方法有两个问题(在本地/开发环境中):

  1. node_modules文件夹仅在我的容器中,但主机的代码编辑器(我的是 VSC)可能需要此文件夹才能正常工作。比如你没有,VSC会骂你他找不到导入的模块……

  2. 如果主机想要安装一个包,yarn add ...他将不得不重新启动并重建要安装的包的容器。

所以我想出了另一个想法,如果我CMD在 Dockerfile 中安装依赖项(或文件中command服务的属性)怎么办docker-compose。因此,Docker 将与主机共享node_modules. 但这是主要问题,node_modulesroot:root权限访问,所以如果你的主机的用户名被命名mint并且不具有相同的名称uidgid你将需要运行 root 访问命令来安装/删除依赖项(例如sudo yarn add ...)。

这是我当前的配置:

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
Run Code Online (Sandbox Code Playgroud)

Dockerfile

FROM node:12.8.1-alpine

WORKDIR /usr/src/app

COPY . .
Run Code Online (Sandbox Code Playgroud)

package.json

{
  "dependencies": {
    "express": "^4.17.1"
  }
}
Run Code Online (Sandbox Code Playgroud)

server.js

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
Run Code Online (Sandbox Code Playgroud)

然后你可以尝试运行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
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,每个文件/文件夹都mint:mint可以访问,除了node_modules(mint是我的主机的用户)。这就是第二个解决方案的问题。

最后,我的问题是:有没有更好的方法来完成这一切?

Cra*_*zit 2

自从我最初写这个问题以来已经过去了几年。我想回来分享不同的观点,因为从那时起我的观点发生了一些变化,我现在认为我想要使用容器的方式是不正确的。

首先,几乎在容器中创建的任何文件/文件夹都不应该在同一容器之外进行更改。在本文中,任何更改node_modules文件夹的命令都应从容器内运行。我知道这可能有点麻烦,但我认为只要你使用 docker-compose (例如docker-compose exec app npm i)就可以了。我认为它更适合 OCI 容器的使用方式。

在操作系统兼容性方面,由于一切(与开发环境相关的)都应该从容器内部完成,所以不应该有任何问题。请注意,我见过组织分发带有已卸载和预安装依赖项的开发映像。我认为两种方式都很好,这实际上取决于您是否想要轻量级的开发映像。