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

时间:2014-10-16 13:49:00

标签: grails filesystems vagrant docker

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

  1. MacOSX工作站运行...
  2. Vagrant VirtualBox虚拟机,ubuntu/trusty64正在运行...
  3. Docker容器正在运行......
  4. 我用Grails编写的应用程序
  5. 每个图层的配置方式都是从上面的图层共享文件系统的一部分。这样:

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

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

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

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

3 个答案:

答案 0 :(得分:1)

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

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

操作系统事件(Linux上的inotify,OS X上的FSEvents),由于文件操作通过操作系统子系统,因此可以检测到更改。这在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 

在流浪汉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很好。

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

答案 1 :(得分:1)

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

  1. 创建两个文件夹,一个用于映射项目,另一个用于"镜像"
  2. 将项目映射到第一个文件夹
  3. 让后台脚本在容器中运行,将项目文件夹撤至"镜像"
  4. 从"镜像"
  5. 运行项目

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

    未在较大的项目中测试,但在我的情况下,我没有意识到性能问题。

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

答案 2 :(得分:0)

Vagrant已经包含了一些用于rsync的选项,因此没有必要在主机上安装特殊程序。

在Vagrantfile中,我配置了rsync:

config.vm.synced_folder ".", "/vagrant", type: "rsync",  rsync__exclude: [ "./build", ".git/" ]

然后在命令行中(在主机中)运行:

vagrant rsync

从主机到访客执行一次同步。

vagrant rsync-auto

检测到主机上的更改时,它将自动运行。

请访问https://eresearch.fidelity.com/eresearch/markets_sectors/sectors/si_performance.jhtml?tab=siperformanceVagrant rsync Documentation