在Docker容器中运行命令并自动与主机同步

38次阅读
没有评论

问题描述

在将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文件中使用卷来同步容器内的文件更改与主机之间的文件。具体步骤如下:

  1. docker-compose.yml文件中,为你想要同步的目录创建卷。

yaml
volumes:
- ./client/src:/usr/app/src
- ./client/public:/usr/app/public

这将会把你的本地目录与容器内的目录进行映射,使得两者之间的更改能够相互同步。

  1. 在容器内安装npm包时,更新的内容会直接反映在映射的本地目录中。这样,主机上的文件也会自动更新。

  2. 运行docker-compose build或其他相关命令时,容器内的更改会保留,并且不会覆盖本地的更改。

注意事项和建议

  • 在使用卷进行文件同步时,请注意可能存在的权限问题。确保容器内的用户权限与主机上的用户权限保持一致,以避免访问问题。
  • 如果你的应用程序依赖于一些主机环境变量或配置文件,你可能需要相应地配置容器内的环境变量,以确保容器内部的应用程序能够正常工作。

使用卷可以让你在Docker容器内和主机之间进行文件同步,从而更好地实现了应用程序的Docker化目标。这将使多个开发人员能够在一个统一的环境中进行开发,同时又能够享受Docker化带来的便利性和可移植性。

正文完