Docker Compose运行Golang(air)+Vue3项目热重载不生效如何解决
Docker Compose 运行服务时热重载失效排查与修复方案
问题现象
- 宿主机环境:Linux Pop!_OS,内核版本5.17.5-76051705-generic
- 部署架构:通过Docker Compose同时部署Vue前端、Golang后端API服务,后端使用cosmtrek/air工具实现Go代码热重载
- 正常基线:air直接在宿主机运行时热重载功能完全正常;相同docker-compose配置在MacBook设备上可正常触发热重载;bind mount绑定挂载本身功能正常(容器内修改文件可同步到宿主机,宿主机修改文件名的操作容器内可观测)
- 异常表现:
- 宿主机通过VSCode编辑代码时,容器内运行的air无法触发热重载
- 容器内安装Nano直接编辑代码时,热重载可正常工作,修改内容可同步到宿主机VSCode
- 反向同步存在事件断层:容器内打开Nano编辑文件时,宿主机VSCode修改的内容无法被已打开的Nano实时感知,必须关闭Nano重新打开才能看到变更,本质是宿主机产生的文件变更事件无法传递给容器内已打开对应文件的进程
当前现有配置
Golang服务Dockerfile
FROM golang:1.18.0 RUN apt update && apt upgrade -y && \ apt install -y git \ make openssh-client WORKDIR /app RUN curl -fLo install.sh https://raw.githubusercontent.com/cosmtrek/air/master/install.sh \ && chmod +x install.sh && sh install.sh && cp ./bin/air /bin/air CMD air
Go API服务docker-compose.yaml配置
api: container_name: golang_api build: context: ./api depends_on: - database volumes: - ./api:/app ports: - ${PORT}:${PORT} restart: unless-stopped
根因说明
该问题是Linux环境下Docker bind mount的事件机制差异导致:
Mac/Windows平台的Docker Desktop自带专用文件同步组件,会把宿主机上所有文件变更事件完整转发到容器内;但原生Linux环境的Docker bind mount直接基于内核挂载实现,inotify事件随mount namespace隔离,宿主机侧进程修改文件产生的变更事件不会进入容器的事件队列,只有容器内部进程产生的文件修改能被inotify捕获,这也是容器内用Nano编辑能触发热重载、宿主机编辑不行的核心原因。
修复步骤
- 调整air配置,开启轮询模式
在Go项目根目录(即挂载到容器/app的目录)下创建.air.toml配置文件,添加/修改以下配置,绕开inotify依赖,改用定时轮询检测文件变更:
[root] tmp_dir = "tmp" [build] cmd = "go build -o ./tmp/main ." bin = "tmp/main" include_ext = ["go", "tpl", "tmpl", "html"] exclude_dir = ["assets", "tmp", "vendor", "node_modules"] [watch] # 开启轮询,不依赖inotify事件 poll = true # 轮询间隔,单位毫秒,500可兼顾性能和实时性 poll_interval = 500
- 调整docker-compose挂载配置
修改api服务的配置,优化挂载策略、调整容器内inotify参数上限,避免监听失败:
api: container_name: golang_api build: context: ./api depends_on: - database volumes: - ./api:/app:cached ports: - ${PORT}:${PORT} restart: unless-stopped sysctls: fs.inotify.max_user_watches: 524288 fs.inotify.max_user_instances: 512
调整VSCode本地保存配置
打开VSCode设置,搜索files.useAtomicSave并关闭该选项,避免VSCode保存时通过临时文件替换的方式写入,减少跨挂载点的事件识别异常。重建容器生效
执行以下命令重建api服务即可:
docker-compose up -d --build api
补充说明:如果Vue前端热重载也存在同类失效问题,可通过相同思路修复:Vite项目在配置中设置
server.watch.usePolling = true,webpack项目配置watchOptions.poll = 500即可解决Linux下Docker挂载的事件不触发问题。
内容的提问来源于stack exchange,提问作者Elar Saks
相关产品推荐
相关产品推荐

