在Vagrant虚拟机内部运行的Docker容器中,Grails监视文件不起作用

我有一个相当嵌套的结构:

  1. MacOSX工作站正在运行…
  2. ubuntu/trusty64 VirtualBox虚拟机与ubuntu/trusty64运行…
  3. Docker容器正在运行…
  4. 我用Grails编写的应用程序

每个图层的configuration方式都是从上面的图层共享文件系统的一部分。 这条路:

  • Vagrant,在Vagrantfileconfig.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操作:

http://drunomics.com/en/blog/syncd-sync-changes-vagrant-box(Linux)https://github.com/ggreer/fsevents-tools(OS X)

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都很好。

希望这可以帮助别人! 花了我一天的时间来弄清楚这些东西。

我发现在容器中可见的文件系统通知的最佳方式如下:

  1. 创build两个文件夹,一个映射项目和一个“镜像”
  2. 将项目映射到第一个文件夹中
  3. 保持在容器中运行的后台脚本,将项目文件夹rsyncing“镜像”
  4. 从“镜像”运行项目

这可能不是最有效或最优雅的方式,但这种方式对容器的用户是透明的。 不需要额外的脚本运行。

没有在大型项目中testing,但在我的情况下,我没有意识到性能问题。

https://github.com/altieres/docker-jekyll-s3