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

2024-03-06

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

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

每层都以共享上一层文件系统的一部分的方式配置。这边走:

  • 流浪者,与config.vm.synced_folder指令中Vagrantfile
  • Docker,与-v命令如 switch 和VOLUME指令中的Dockerfile

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

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

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


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

Polling,这意味着以一定的时间间隔检查文件夹中所有文件的时间戳。达到“近乎即时”的变化检测需要非常短的时间间隔。这是 CPU 和磁盘密集型的。

操作系统事件(Linux 上为 inotify,OS X 上为 FSEvents),其中的更改是可检测的,因为文件操作会通过操作系统子系统。这对 CPU 和磁盘来说很容易。

网络文件系统 (NFS) 等不会生成事件。由于文件更改不会通过来宾操作系统子系统,因此操作系统不知道更改;仅操作系统making更改(OS X)知道它们。

Grails 和许多其他文件观察器工具依赖于 FSEvents 或 inotify(或类似)事件。

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

弥补这一差距的机制可能涉及一个监视主机变化并触发客户机同步的进程。

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

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

Rsync 到来宾 (Docker) 实例上的非 NFS 文件夹具有 I/O 性能显着提高的额外优势。 VirtualBox 的股票速度慢得令人痛苦。

Update!

这就是我所做的。首次安装lsyncd(OS X 示例,更多信息位于http://kesar.es/tag/lsyncd/ 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"
    },
}

其作用是同步文件夹demo在我的 Vagrant 文件夹中到来宾操作系统中/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

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

总结一下:

  • 在 Mac 上编辑项目文件,在 VM 上执行
  • 使用 lsyncd 将更改同步到虚拟机内的文件夹
  • Grails 注意到更改并触发重新加载
  • 不使用 VirtualBox 共享,磁盘性能更快

Issues:Textmate 触发 lsyncd(尚)无法识别的 FSEvent 类型,因此不会检测到更改。不过,Vim 和 IntelliJ 都很好。

希望这对某人有帮助!我花了一天时间才弄清楚这些东西。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐