[英]Sharing the `node_modules` folder between the container and the host
這是一個非常討論的話題,但我從未找到解決方案。
因此,您可能知道,當我的容器中有一個卷並且我在 Dockerfile 中使用yarn install
安裝我的依賴項時,Yarn 將在我的容器上創建一個具有root:root
訪問權限的node_modules
文件夾。
這種方法有兩個問題(在本地/開發環境中):
node_modules
文件夾僅在我的容器中,但主機的代碼編輯器(我的是 VSC)可能需要此文件夾才能正常工作。 比如你沒有,VSC會罵你他找不到導入的模塊……
如果主機想使用yarn add ...
安裝一個包yarn add ...
他將不得不重新啟動並重建要安裝的包的容器。
所以我想出了另一個想法,如果我在 Dockerfile 中使用CMD
(或 docker docker-compose
文件中服務的command
屬性)安裝依賴項會怎樣。 因此,Docker 將與主機共享node_modules
。 但這里是主要問題, node_modules
有一個root:root
權限訪問,所以如果你的主機的用戶名被命名為mint
並且沒有相同的uid
和gid
你將需要運行 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_modules
( mint
是我的主機的用戶)。 這就是第二個解決方案的問題。
最后,我的問題是:有沒有更好的方法來完成這一切?
在您的情況下,為了讓它以您想要的方式工作,您應該在 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.