React 热重载在 docker 容器中不起作用

React hot reload doesn't work in docker container

我正在尝试使用 docker 设置 React,但由于某种原因我无法让热重载工作。目前,如果我创建一个文件,它会重新编译,但如果我更改文件中的某些内容,它不会。另外,我没有更改任何包或配置文件,项目是用 npx create-react-app projectname --template typescript.

生成的

通过在线研究,我发现我需要将 CHOKIDAR_USEPOLLING=true 添加到 .env 文件中,我试过了但没有用,我尝试将 .env 放在所有目录中以防万一把它放在错误的地方。我还将它添加到 docker-compose.yml 环境中。

除此之外,我还尝试将 react-scripts 降级到 4.0.3,因为我发现 this,这也没有用。

我还尝试在本地更改文件,然后检查它是否也在 docker 容器内更改,确实如此,所以我很确定我的 docker 相关文件是正确的。

版本

目录结构

project/
│   README.md
│   docker-compose.yml    
│
└───frontend/
    │   Dockerfile
    │   package.json
    │   src/
    │   ...

Docker文件

FROM node:16.14-alpine3.14

WORKDIR /app

COPY package.json .
COPY package-lock.json .
RUN npm install 

CMD ["npm", "start"]

docker-compose.yml

services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    volumes:
      - "./frontend:/app"
      - "/app/node_modules"
    environment:
      CHOKIDAR_USEPOLLING: "true"

我曾经遇到过同样的问题,这个问题在我的 Dockerfile 中工作目录是 /var/app/ 而在我的 docker-compose.yml 中我将当前工作目录安装到 /var/app/frontend,我刚刚删除了那个 /frontend 并且工作正常。请检查你的。谢谢

您拥有的 Dockerfile 非常适合将您的应用程序打包到容器中以准备部署。如果您希望将源放在容器之外并让 运行ning 容器对源中的更改做出反应,这对于开发来说不是很好。

我所做的是保留用于打包应用程序的 Dockerfile,并仅在完成后构建它。

在开发时,我经常可以在没有 dockerfile 的情况下进行开发,只需 运行 构建一个容器并将我的源代码映射到其中即可。

例如,这是我用来 运行 节点应用程序

的命令
docker run -u=1000:1000 -v $(pwd):/app -w=/app -d -p 3000:3000 --rm --name=nodedev node bash -c "npm install && npm run dev"

如您所见,它只是 运行 一个标准节点图像。让我来看看命令的不同部分:

-u 1000:1000 1000是我在主机上的UID和GID。通过 运行 使用相同的 ID 连接容器,容器创建的任何文件都将在主机上归我所有。

-v $(pwd):/app将当前目录映射到容器中的/app目录下

-w /app设置容器中的工作目录为/app

-d运行超脱

-p 3000:3000 将容器中的端口 3000 映射到主机上的 3000

--rm 退出时删除容器

-name=nodedev给它起个名字,我不用查名字就杀了它

最后有一个用于容器 bash -c "npm install && npm run dev" 的命令,它首先安装任何依赖项,然后 运行s package.json 文件中的开发脚本。该脚本以热重新加载的模式启动节点。

如果您使用 Windows 并使用 react-scripts 5.x.x 或更高版本,则 CHOKIDAR_USEPOLLING 无法正常工作。按以下方式更改您的 package.json:

    "scripts": {
    ...
    "start": "WATCHPACK_POLLING=true react-scripts start",
    ...
  }

轮询不是我的问题——观察 docker 输出我发现它重新编译正确。我的问题与热加载器中的网络有关。我发现浏览器正在尝试打开一个 websocket 返回到节点服务器 ws://localhost:3000/sockjs-node 但无论我的计算机上的网络设置如何,这都不会路由回 docker 容器。我加了

WDS_SOCKET_HOST=127.0.0.1

到环境变量。重启后浏览器成功连接ws://127.0.0.1:3000/sockjs-node,热重载正常

这与使用类似于原始 post 的 docker-compose 解决方案有关。我也可以使用 docker 运行 方法的变体来制作东西,但启动速度要慢得多。