问题描述
在将MENN(Next.js)堆栈应用程序Docker化后,遇到了一些问题。在安装npm包时遇到了困难。首先,让我展示一下项目结构:
src/server/Dockerfile
FROM node:14-alpine
WORKDIR /usr/app
COPY package*.json ./
RUN npm install -qyg nodemon@2.0.7
RUN npm install -qy
COPY . .
CMD ["npm", "run", "dev"]
src/client/Dockerfile
FROM node:14-alpine
WORKDIR /usr/app
COPY package*.json ./
RUN npm install -qy
COPY . .
CMD ["npm", "run", "dev"]
src/docker-compose.yml
version: "3"
services:
client:
build:
context: ./client
dockerfile: Dockerfile
ports:
- 3000:3000
networks:
- mern-network
volumes:
- ./client/src:/usr/app/src
- ./client/public:/usr/app/public
depends_on:
- server
environment:
- REACT_APP_SERVER=http://localhost:5000
- CHOKIDAR_USEPOLLING=true
command: npm run dev
stdin_open: true
tty: true
server:
build:
context: ./server
dockerfile: Dockerfile
ports:
- 5000:5000
networks:
- mern-network
volumes:
- ./server/src:/usr/app/src
depends_on:
- db
environment:
- MONGO_URL=mongodb://db:27017
- CLIENT=http://localhost:3000
command: /usr/app/node_modules/.bin/nodemon -L src/index.js
db:
image: mongo:latest
ports:
- 27017:27017
networks:
- mern-network
volumes:
- mongo-data:/data/db
networks:
mern-network:
driver: bridge
volumes:
mongo-data:
driver: local
目前,如果我在主机上使用npm安装任何包,它会如预期地更新package.json文件。如果运行docker-compose build
命令,package.json文件也会更新到容器内部,这是正常的。但是,我觉得这似乎违背了将应用程序Docker化的初衷!如果多个开发人员需要在此应用程序上工作,并且他们都需要在自己的机器上安装node/npm,那么使用Docker还有什么意义呢?除了用于部署之外,我现在的做法是:
sudo docker exec -it cebc4bcd9af6 sh // 登录到服务器容器
npm i express // 运行命令
这将安装该包并更新package.json,但主机上的package.json不会更新。如果再次运行build
命令,所有更改都会丢失,因为Dockerfile会将主机的源代码复制到容器中。有没有一种方法可以同步客户端和主机?以这样一种方式,如果我在容器内安装了一个包,那么它也应该更新主机文件?这样,我就不需要在本地安装node/npm,也能实现应用程序Docker化的目标。
解决方案
在Docker容器中同步主机文件的需求相对复杂,因为容器内和主机之间的文件系统是分离的。然而,你可以通过使用卷(volumes)来实现这一目标,使得容器内的更改可以反映在主机上。
以下是一种可能的解决方案:
使用卷(Volumes)来同步文件
卷是Docker中用于持久化存储和共享数据的一种机制。你可以在docker-compose文件中使用卷来同步容器内的文件更改与主机之间的文件。具体步骤如下:
- 在
docker-compose.yml
文件中,为你想要同步的目录创建卷。
yaml
volumes:
- ./client/src:/usr/app/src
- ./client/public:/usr/app/public
这将会把你的本地目录与容器内的目录进行映射,使得两者之间的更改能够相互同步。
-
在容器内安装npm包时,更新的内容会直接反映在映射的本地目录中。这样,主机上的文件也会自动更新。
-
运行
docker-compose build
或其他相关命令时,容器内的更改会保留,并且不会覆盖本地的更改。
注意事项和建议
- 在使用卷进行文件同步时,请注意可能存在的权限问题。确保容器内的用户权限与主机上的用户权限保持一致,以避免访问问题。
- 如果你的应用程序依赖于一些主机环境变量或配置文件,你可能需要相应地配置容器内的环境变量,以确保容器内部的应用程序能够正常工作。
使用卷可以让你在Docker容器内和主机之间进行文件同步,从而更好地实现了应用程序的Docker化目标。这将使多个开发人员能够在一个统一的环境中进行开发,同时又能够享受Docker化带来的便利性和可移植性。