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

问题描述 投票:5回答:3

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

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

每一层都配置为从上一层共享文件系统的一部分。这样:

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

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

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

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

grails filesystems vagrant docker
3个回答
1
投票
有两种检测文件更改的方法(我知道):

Polling,表示以一定间隔检查文件夹中所有文件的时间戳。到达“近乎即时”的变化检测需要非常短的间隔。这会占用大量CPU和磁盘。

OS Events

(在Linux上为inos,在OS X上为FSEvents),由于文件操作通过OS子系统,因此可以检测到更改。在CPU和磁盘上这很容易。网络文件系统(NFS)等不会生成事件。由于文件更改不会通过来宾OS子系统传递,因此OS无法识别更改。只有OS

make所做的更改(OS X)知道它们。

Grails和许多其他File Watcher工具取决于FSEvents或inotify(或类似的)事件。

那该怎么办?考虑到可能产生的流量,在正常情况下从主机“广播” NFS变化到所有来宾是不切实际的。但是,我认为VirtualBox共享应视为特殊例外...

弥合这种差距的机制可能涉及监视主机更改并触发来宾同步的过程。

检查这些文章以获取一些有趣的想法和解决方案,其中涉及某种类型的rsync操作:

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

与来宾(Docker)实例上的非NFS文件夹同步具有另一个优点,即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中的来宾OS。请注意,您需要使用SSH密钥设置登录名,以使此过程顺利进行。

然后,在运行无用虚拟机的情况下,我启动了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将更改重新同步到VM内的文件夹中
  • Grails注意到更改并触发重新加载
  • 不使用VirtualBox共享,磁盘性能要快得多
  • 问题:

  • Textmate触发了lsyncd无法识别(但尚未识别)的FSEvent类型,因此未检测到更改。不过,Vim和IntelliJ都很好。 希望这可以帮助某人!花了我一天的时间弄清楚这些东西。

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

      创建两个文件夹,一个用于映射项目,另一个用于创建“镜像”
    1. 将项目映射到第一个文件夹中
    2. 保持容器中运行的后台脚本,将项目文件夹同步到“镜像”
    3. 从“镜像”运行项目
  • 这可能不是最有效或最优雅的方法,但是这种方法对容器的用户是透明的。无需运行其他脚本。

    未在较大的项目中进行测试,但就我而言,我没有意识到性能问题。

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


  • 0
    投票
    Vagrant已经包含一些用于rsync的选项,因此不必在主机上安装特殊程序。

    在Vagrantfile中,我配置了rsync:

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

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

    vagrant rsync

    哪个将执行从主机到访客的单个同步。

    vagrant rsync-auto

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

    [在Vagrant rsync Documentationrsync-auto上查看更多内容

    © www.soinside.com 2019 - 2024. All rights reserved.