寰宇网

docker for windows不响应react项目改变后的重编译

docker一般用于部署,但也可以用于统一开发环境,解决诸如前后端分离后单边开发者无法获得一个完整的开发环境的问题。所以我写了这个项目简单实践一下用docker来简化开发环境。其中遇到了一个docker在windows下表现不正常的问题及其解决方案。

项目概述

项目主要是用react编写一个blog的用户界面,blog项目就要求有一个后端(类似于hexo这种静态网页生成器模式的blog不算),能提供诸如注册、登录、发表文章、编辑文章、删除文章之类的功能。

这种简单的CRUD后端还是非常简单的,之前就写过,但是如何让前端项目能愉快地调用后端呢?

一种方案是后端先部署上线运行着,配置好CORS,前端项目直接调线上接口,这种方式其实蛮好,而我现所在的公司也是使用这种方式进行开发的(在此吐槽一下老东家,使用的是前端自行mock数据的方式,当然,技术选型有多方面的考虑)。

但这种方式在个人小项目中有个问题,很有可能后端也只是个demo级的东西,非常不完善,服务器资源又有限,指不定哪天就挂掉了。换而言之,很难让一个项目能在任何人的电脑上都愉快地运行。

另一种方案就是后端一起给出,CORS也不用配了,用个nginx来代理,session\cookie都能用,好不好哇?

你问我好不好我当然说好啦,但一个正常的前端会配置jdk,运行mvn,安装启动数据库,配置nginx的概率有多大呢?不知道。

这个时候就是Docker出场的时间了,配置好四个docker镜像,用docker-compose编排好容器,一个up就启动了全套的开发环境。

仔细去数了一下,从0启动整套开发环境只需要打4行命令,当然,等待docker从hub拉image的时间会取决于你的网速,所以第一次会慢一些,后续只需要 docker-compose up 一条命令即可啦。

遇到的问题

在mac上表现一切正常,up之后访问 localhost:8080 即可看到效果,用IDE或者编辑器打开项目,编辑内容,保存。在短暂的等待后就能看到改动后的网页啦(使用的create-react-app生成项目模板,live reload之类的都是配置好的)。

然而Windows上的表现却不正常,启动是能启动,看网页也能看到。就是编辑文件保存以后,不会触发webpack的重新编译,看不到网页新的效果。要想看新的效果呢……就重新来一遍 docker-compose up ,哇,这就很难受了。

只是想改个小地方看看,还得等整套容器编排重新启动一遍,这是不可接受的。

问题的表现就是,docker for windows里,windows下改了文件,docker容器里没有反应。这个表现的原因可能是两种:

  1. 容器里的文件没有改变
  2. 文件改变了,但容器无法感应到改变

为了确认是哪种原因,我进入到相应的node容器里,手工启动 npm start ,然后在Windows下编辑文件并保存。确实没有重编译,于是我停掉 npm start ,cat对应的文件查看是否是我改动后的样子。

确认是原因2,即某种原因导致了docker for windows的容器无法感应到windows通过volume关联来的文件夹里文件的变化。

如何解决

之所以想写这篇文章,也是希望后来有用中文关键字来搜索的同学有机会找到解决方案,会用英文直接搜到那是最吼的啦。

Google几番搜索后找到了docker论坛里这个帖子,简单理解了下问题原因:

Docker for Windows relies on SMB/CIFS support in Linux, and since propagating filesystem notifications is not supported our options are limited.

Docker for Windows 依赖于Linux对SMB/CIFS的支持,但是由于文件系统的通知冒泡不支持,我们的能力受限。

一般来说,到这个地方就算走到 bad ending ,大家可以洗洗睡了,然而,却有脑洞颇大的同学给出了一个python包,提出了一个hack方案。感谢作者。

python包:docker-windows-volume-watcher,这个东西的原理就是它运行在Windows里,观测到文件的变化后,先读取文件的权限,再重写权限值为读取的这个值(等于没变),容器里的Linux就能检测到这个重写权限的变化,认为是文件变了,实现了通知容器这个文件变了的效果。

所以,现在Windows的同学也可以愉快地一行命令启环境然后尽情开发啦。