簡體   English   中英

在容器和主機之間共享 `node_modules` 文件夾

[英]Sharing the `node_modules` folder between the container and the host

這是一個非常討論的話題,但我從未找到解決方案。

因此,您可能知道,當我的容器中有一個卷並且我在 Dockerfile 中使用yarn install安裝我的依賴項時,Yarn 將在我的容器上創建一個具有root:root訪問權限的node_modules文件夾。

這種方法有兩個問題(在本地/開發環境中):

  1. node_modules文件夾僅在我的容器中,但主機的代碼編輯器(我的是 VSC)可能需要此文件夾才能正常工作。 比如你沒有,VSC會罵你他找不到導入的模塊……

  2. 如果主機想使用yarn add ...安裝一個包yarn add ...他將不得不重新啟動並重建要安裝的包的容器。

所以我想出了另一個想法,如果我在 Dockerfile 中使用CMD (或 docker docker-compose文件中服務的command屬性)安裝依賴項會怎樣。 因此,Docker 將與主機共享node_modules 但這里是主要問題, node_modules有一個root: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

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_modulesmint是我的主機的用戶)。 這就是第二個解決方案的問題。

最后,我的問題是:有沒有更好的方法來完成這一切?

在您的情況下,為了讓它以您想要的方式工作,您應該在 docker 文件中添加USER ,在 docker-compose.yml 中添加user: 例如

Dockerfile:

FROM node:12.8.1-alpine

WORKDIR /usr/src/app

USER node

COPY . .

docker-compose.yml:

version: '3.7'

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

無論如何,我們遇到了類似的情況,我們選擇了不同的方法。 我們決定避免在 docker-compose.yml 中安裝 node_modules 文件夾,而不是在主機和容器之間共享 node_modules 文件夾(如果您與使用不同操作系統的同事一起工作,這是令人討厭的行為)。

在我們的例子中,Dockerfile 看起來像這樣:

FROM node:8.12.0-stretch

RUN mkdir /api

WORKDIR /api

COPY ./package.json ./package-lock.json ./
RUN npm ci --prod

COPY . .

CMD [ "nodemon", "server.js" ]

docker-compose.yml 如下所示:

version: '3.7'

services:
  app:
    build: .
    volumes:
      - "./:/api"
      - "/api/node_modules/"

這樣我們就可以在主機中創建 node_modules(可用於測試、開發等)並安全地保持 docker 容器的內容不變。 這種方法的缺點是我們的開發人員還必須在主機上運行npm ci ,並且每次更改 package.json 時他們都需要重新創建映像。

一般來說,我不會推薦這種方法,因為您是主機和容器可能無法共享相同的模塊。 例如,如果您團隊中的其他人使用 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/卷,因為它將在容器內覆蓋它。 此外,尾部斜杠很重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM