【问题标题】:How do I configure my Docker React container to only install modules when it needs them?如何将我的 Docker React 容器配置为仅在需要时安装模块?
【发布时间】:2020-05-27 20:30:26
【问题描述】:

我正在尝试在我的 docker-compose.yml 文件中构建几个 Docker 服务,这些服务将启动我的 Django/MySql 后端以及我的 React 客户端应用程序。我的 docker-compose.yml 中有这个部分来处理 React 部分 ....

  client:
    build:
      context: ./client
    volumes:
      - ./client:/app
    ports:
      - '3001:3000'
    restart: always
    container_name: web-app
    environment:
      - NODE_ENV=development
      - REACT_APP_PROXY=http://localhost:9090
    depends_on:
      - web

然后我构建了以下客户端/Dockerfile 来配置 React 容器...

FROM node:10-alpine AS alpine

# A directory within the virtualized Docker environment
# Becomes more relevant when using Docker Compose later
WORKDIR /app/

# Copies package.json and package-lock.json to Docker environment
COPY package*.json ./

# Installs all node packages
RUN npm install

# Finally runs the application
CMD [ "npm", "start" ]

但是当我的容器启动时,它会因以下错误而死...

web-app   | Failed to compile.
web-app   | 
web-app   | ./node_modules/react-tag-input/dist-modules/components/ReactTags.js
web-app   | Module not found: Can't resolve 'react-dnd' in '/app/node_modules/react-tag-input/dist-modules/components'

我认为我上面的“RUN npm install”会节省一天的时间,但我想不会。有没有办法以某种方式检测哪些模块未安装并在我的容器启动时安装它们?

编辑: package.json

{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.4.0",
    "@testing-library/user-event": "^7.2.1",
    "bootstrap": "^4.4.1",
    "jquery": "^1.9.1",
    "react": "^16.12.0",
    "react-bootstrap": "^1.0.0-beta.17",
    "react-device-detect": "^1.12.1",
    "react-dom": "^16.12.0",
    "react-hamburger-menu": "^1.2.1",
    "react-native-flash-message": "^0.1.15",
    "react-router-dom": "^5.1.2",
    "react-scripts": "3.3.1",
    "react-tag-input": "^6.4.3",
    "typescript": "^3.8.3"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "NODE_ENV=development react-scripts build",
    "build:prod": "NODE_ENV=production react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "proxy": "http://localhost:8000",
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

【问题讨论】:

  • 您可以添加您的package.json 吗?
  • @nischay goyal,它被添加为我的问题的编辑
  • 只是想检查 react-dnd 是否应该是 package.json 的一部分?如果没有,你能添加docker build -t imageName .的输出吗?
  • @nischay goyal,是的,它应该在那里。我试图从这里获取组件 - npmjs.com/package/react-tag-input ,但没有正确安装。显然运行“npm install --save react-tag-input”并没有安装所有依赖项,我必须进去单独安装。
  • 我认为您需要在 package.json 中正确添加所有依赖项,然后运行 ​​npm install 它应该可以工作。

标签: reactjs docker docker-compose dockerfile npm-install


【解决方案1】:

这里发生了两件事:

  1. 您的volumes: 指令会覆盖/app 树中的所有内容,包括node_modules
  2. 您的 Dockerfile 实际上并未将应用程序代码COPY 放入映像中(因此您需要使用volumes: 的解决方法将其放在那里)。

您可以通过更新 Dockerfile 来解决此问题

FROM node:10-alpine
WORKDIR /app/
COPY package*.json ./
RUN npm install

# Actually copy the application code in
COPY . ./

CMD ["npm", "start"]

如果您还没有.dockerignore 文件,请创建包含node_modules 行的文件,以防止该主机目录被构建到映像中。

最后,从您的docker-compose.yml 文件中删除volumes:

如果您更改前端代码,您将需要docker-compose up --build 以重新构建图像。

如果您想要一个实时开发环境,您可以直接在主机上使用 Node,即使您堆栈的其余大部分都在 Docker 中运行。对于前端代码尤其如此:因为所提供的代码实际上是在最终用户的浏览器中运行的,所以它不能直接与 Docker 网络通信,或者根本无法真正利用 Docker 中的优势。

# Start everything besides the front-end
docker-compose up -d web

# Start a dev server in the usual way
export NODE_ENV=development
export REACT_APP_PROXY=http://localhost:9090
npm start

【讨论】:

  • 我不会考虑 COPY 代码选项,除非他复制了部分 Dockerfile
  • 嗨@DavidMaze,感谢您提供这个有见地的回答。我想保持在我的客户端(前端)项目中本地编辑文件的能力,并让 docker 映像自动重新编译应用程序。如果我实施您的解决方案,每次我在前端应用程序中编辑文件时,我是否都必须重建我的 docker 映像?
猜你喜欢
  • 2019-12-05
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 2020-10-28
  • 2019-06-01
  • 2013-08-04
  • 1970-01-01
  • 2022-01-15
相关资源
最近更新 更多