gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 09:29:35 28 4
gpt4 key购买 nike

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

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

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

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

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

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

有人知道可能是什么原因和/或我如何调试这个问题吗?

最佳答案

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

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

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

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

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

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

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

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

http://drunomics.com/en/blog/syncd-sync-changes-vagrant-box (Linux) https://github.com/ggreer/fsevents-tools (操作系统)

Rsync-ing 到 guest (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 中的 guest 操作系统。请注意,您需要使用 SSH key 设置登录,以使此过程顺利进行。

然后,随着 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 上编辑项目文件,在虚拟机上执行
  • 使用 lsyncd 将更改同步到虚拟机内的文件夹
  • Grails 注意到更改并触发重新加载
  • 不使用 VirtualBox 共享,磁盘性能更快

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

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

关于Grails 监视文件在 Vagrant 虚拟机内运行的 Docker 容器中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26406130/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com