在Vagrant虚拟机内部运行的Docker容器中,Grails监视文件不起作用
我有一个相当嵌套的结构:
- MacOSX工作站正在运行…
-
ubuntu/trusty64
VirtualBox虚拟机与ubuntu/trusty64
运行… - Docker容器正在运行…
- 我用Grails编写的应用程序
每个图层的configuration方式都是从上面的图层共享文件系统的一部分。 这条路:
- Vagrant,在
Vagrantfile
有config.vm.synced_folder
指令 - Docker,在
Dockerfile
使用-v
命令,如switch和VOLUME
指令
这样,我可以在我的工作站上进行开发,底部的Grails应用程序应该(理想情况下)检测更改并重新编译/重新加载。 当我在MacOSX上直接运行相同的应用程序时,这是一个function,但现在grails似乎完全不知道文件更改。 当然,如果我用一个编辑器(在Docker容器中)打开这些文件,它们确实发生了变化,事实上,如果我停止/重新启动grails应用程序,则会使用新的代码。
我不知道Grails如何实现观察策略,但是如果它依赖于某些操作系统级别的function,我怀疑文件更改通知会丢失在链中某处。
任何人都有一个想法,可能是什么原因和/或我怎么可以去debugging呢?
有两种方法来检测文件更改(我知道):
轮询 ,这意味着以一定的时间间隔检查文件夹中所有文件的时间戳。 进行“接近即时”的变化检测需要非常短的时间间隔。 这是CPU和磁盘密集型。
OS事件 (在Linux上是inotify,在OS X上是FSEvents),由于文件操作通过操作系统子系统,可以检测到更改。 这在CPU和磁盘上很容易。
networking文件系统(NFS)等不会生成事件。 由于文件更改不通过来宾操作系统子系统,操作系统不知道更改; 只有进行更改的操作系统(OS X)知道它们。
Grails和其他许多File Watcher工具依赖于FSEvent或inotify(或类似的)事件。
那么该怎么办? 考虑到可能产生的stream量,在正常情况下将从主机到所有客户机的NFS变化“广播”是不切实际的。 但是,我认为,VirtualBox的股份应该算作一个特殊的例外…
弥合这种差距的机制可能涉及到一个过程,观察主机的变化,并触发客人的同步。
检查这些文章的一些有趣的想法和解决scheme,涉及一些types的rsync操作:
Rsync到客户(Docker)实例上的非NFS文件夹具有I / O性能显着增加的额外优势。 VirtualBox共享只是非常缓慢。
更新!
这是我做的。 首先安装lsyncd (OS X示例,更多信息请参见 http://kesar.es/tag/lsyncd/ ):
brew install lsyncd
在我Mac上的Vagrant文件夹中,我创build了lsyncd.lua文件:
settings { logfile = "./lsyncd.log", statusFile = "./lsyncd.status", nodaemon = true, pidfile = "./lsyncd.pid", inotifyMode = "CloseWrite or Modify", } sync { default.rsync, delay = 2, source = "./demo", target = "vagrant@localhost:~/demo", rsync = { binary = "/usr/bin/rsync", protect_args = false, archive = true, compress = false, whole_file = false, rsh = "/usr/bin/ssh -p 2222 -o StrictHostKeyChecking=no" }, }
这是什么,将我的Vagrant文件夹中的文件夹demo
同步到/home/vagrant/demo
的客户操作系统。 请注意,您需要使用SSH密钥设置login才能使此过程无摩擦。
然后,随着stream浪的虚拟机运行,我开始了lsyncd进程。 -log Exec
是可选的; 它将其活动logging到stdout:
sudo lsyncd lsyncd.lua -log Exec
在stream浪VM上,我在我的同步文件夹中启动了Grails(2.4.4):
cd /home/vagrant/demo grails -reloading run-app
回到我的Mac上的IntelliJ我编辑了一个控制器类。 它几乎立即触发lsyncd(2秒延迟),之后很快确认了Grails重新编译了这个类。
总结:
- 在Mac上编辑项目文件,在虚拟机上执行
- 使用lsyncd将您的更改rsyncync到虚拟机内的文件夹
- Grails注意到这些更改并触发重新加载
- 通过不使用VirtualBox共享速度更快的磁盘性能
问题: Textmate会触发一种types的lsyncd(尚未)识别的FSEvent,因此无法检测到更改。 但是Vim和IntelliJ都很好。
希望这可以帮助别人! 花了我一天的时间来弄清楚这些东西。
我发现在容器中可见的文件系统通知的最佳方式如下:
- 创build两个文件夹,一个映射项目和一个“镜像”
- 将项目映射到第一个文件夹中
- 保持在容器中运行的后台脚本,将项目文件夹rsyncing“镜像”
- 从“镜像”运行项目
这可能不是最有效或最优雅的方式,但这种方式对容器的用户是透明的。 不需要额外的脚本运行。
没有在大型项目中testing,但在我的情况下,我没有意识到性能问题。