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

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

> MacOSX工作站运行…
>使用ubuntu / trusty64运行的Vagrant VirtualBox虚拟机…
> Docker容器正在运行……
>我用Grails编写的应用程序

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

> Vagrant,在Vagrantfile中使用config.vm.synced_folder指令
> Docker,在Dockerfile中使用-v命令,如switch和VOLUME指令

这样我就可以在我的工作站上进行开发,底部的Grails应用程序应该(理想情况下)检测更改并动态重新编译/重新加载.这是我在MacOSX上直接运行相同应用程序时常用的功能,但现在grails似乎完全不知道文件更改.当然,如果我使用编辑器(在Docker容器内)打开文件,它们确实已经更改,实际上如果我停止/重新启动grails应用程序,则使用新代码.

我不知道grails如何实现监视策略,但如果它依赖于某些操作系统级别的功能,我怀疑文件更改通知会在链中的某处丢失.

任何人都知道可能是什么原因和/或我如何调试这个?

最佳答案 有两种方法可以检测文件更改(我知道):

轮询,这意味着以特定间隔检查文件夹中所有文件的时间戳.进行“近乎即时”的变化检测需要非常短的间隔.这是CPU和磁盘密集型的.

OS事件(Linux上的inotify,OS X上的FSEvents),由于文件操作通过OS子系统,因此可以检测到更改.这在CPU和磁盘上很容易.

网络文件系统(NFS)等不生成事件.由于文件更改不通过客户操作系统子系统,因此操作系统不知道更改;只有进行更改的操作系统(OS X)才知道它们.

Grails和许多其他File Watcher工具依赖于FSEvents或inotify(或类似)事件.

那么该怎么办?考虑到可能产生的流量,在正常情况下“广播”从主机到所有访客的NFS更改是不切实际的.但是,我认为VirtualBox的股票应算作特殊例外……

弥合这一差距的机制可能涉及一个进程,该进程监视主机的更改并触发guest虚拟机上的同步.

查看这些文章,了解一些有趣的想法和解决方案,包括某种类型的rsync操作:

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

与guest虚拟机(Docker)实例上的非NFS文件夹进行Rsync,还具有I / O性能显着提高的额外优势. VirtualBox的份额非常缓慢.

更新!

这就是我做的.首先安装lsyncd(OS X示例,更多信息,请访问http://kesar.es/tag/lsyncd/):

brew install lsyncd

在我Mac上的Vagrant文​​件夹中,我创建了文件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密钥设置登录,以使此过程无摩擦.

然后,随着vagrant VM运行,我启动了lsyncd进程. -log Exec是可选的;它将其活动记录到标准输出:

sudo lsyncd lsyncd.lua -log Exec 

在vagrant VM上,我在同步文件夹中启动了Grails(2.4.4):

cd /home/vagrant/demo
grails -reloading run-app

回到IntelliJ的Mac上我编辑了一个Controller类.它几乎立即触发lsyncd(延迟2秒),之后很快我确认Grails重新编译了这个类!

总结一下:

>在Mac上编辑项目文件,在VM上执行
>使用lsyncd将更改rsync同步到VM中的文件夹
> Grails会注意到更改并触发重新加载
>不使用VirtualBox共享,可以大大提高磁盘性能

问题:Textmate触发lsyncd尚未(尚未)识别的一种FSEvent,因此未检测到更改.不过,Vim和IntelliJ很好.

希望这有助于某人!我花了一天时间来解决这个问题.

点赞