Compose Watch 首次漏同步旧文件,修改后却能同步
Watch 首次没有复制已有文件,编辑后却正常同步,核对旧镜像时间过滤和实际版本。正式 5.5.1 已移除该过滤,路径、忽略和权限仍需检查。
Watch 已显示启用,initial_sync: true 也写了,但容器里没有启动前就存在的源文件;编辑一次文件后,它又能正常同步。先核对 Compose 插件的实际版本。旧实现用文件修改时间与镜像创建时间筛选首次同步内容,可能跳过本来就需要复制的旧文件。
这个时间筛选在已核对的 Compose 2.35.1 和 5.5.0 源码中存在,正式 5.5.1 已移除。该修复针对首次同步,不能解释所有 Watch 不工作的问题,也不表示只要装到某个版本,路径和权限就一定正确。
确认失败的是首次同步
先用实际启动参数读取版本和合并配置:
docker compose version
docker compose config
docker compose ps -a
配置可能展开凭据,分享前脱敏。核对目标服务的 develop.watch:路径是否包含该文件,动作是否是同步,target 是否为应用读取的容器路径,以及最终模型是否确实保留 initial_sync: true。
Watch 适合带本地构建配置的开发服务。下面只是已有服务中的配置片段,保留项目自己的 Dockerfile、入口和其他定义:
services:
app:
build: .
develop:
watch:
- path: ./src
action: sync
target: /app/src
initial_sync: true
./src 要按实际项目路径解析;容器中的目标目录还需允许服务用户写入,并具备 Watch 所需的 stat、mkdir、rmdir 工具。不要把一个仅运行预构建镜像的服务直接改成这段片段,而遗漏自己的构建来源。
如果编辑后能同步,说明至少这次变化事件和目标写入路径能够工作;首次同步分支仍需要单独确认。若编辑后也没变化,应先检查忽略规则、目标权限和 Watch 是否真的在运行。
旧时间筛选如何漏掉文件
旧的目录同步分支会跳过修改时间早于镜像创建时间的文件;单文件分支则只纳入修改时间晚于镜像创建时间的文件。两种比较在时间相等时也有区别,不能归纳成所有目录都失败、所有单文件都正常。
本地源码在构建镜像前已经存在,其修改时间自然可能早于镜像创建时间。等待更久不能改变这个筛选结果。修改文件后产生新的事件能够同步,也不能证明启动时复制已经完成。
正式 5.5.1 移除了这个首次同步的镜像时间过滤,仍保留忽略规则和与 bind 挂载重叠路径的排除。升级时选择当前受维护、符合项目兼容要求的版本;5.5.1 是这里已核证的修复参照,不要求为了排错刻意安装旧版本。
升级后仍要核对排除条件
检查 .dockerignore、Watch 条目自己的 ignore,以及同一服务已有的 bind 挂载。被排除的文件不因升级自动获得同步资格。Dockerfile、Compose 配置等文件也不能一概当作普通源码同步。
修改插件或开发配置前保留原配置和可回退版本,在隔离开发环境验证。重新开始 Watch 会话时,先核对尚未编辑的现有文件是否已到达容器,再检查后续正常编辑是否同步。无需批量修改整个项目的时间戳来制造事件。
initial_sync 也不能当成“应用入口运行前,所有源码必已准备”的通用启动屏障。应用首次启动必需的文件应由镜像构建或明确的启动准备流程提供。若旧文件已同步,应用却仍读旧内容,再检查它实际加载的路径与进程缓存,不继续归因于已经移除的时间筛选。


