7

我正在尝试建立一个开发环境,用于在 docker 容器中开发 play 应用程序。我创建了一个安装了 sbt 的图像。然后,我将主机上的项目文件夹作为卷映射到容器,并以交互模式运行 shell:

docker run -v /Users/jorgen/dev/play-sbt-docker/app:/data/app -w /data/app -p 9999:9000 -i -t jorgenfb/sbt /bin/bash

然后我通过运行启动播放应用程序sbt ~run。播放服务器开始只是找到,当我在主机上编辑我的文件时它甚至会重新编译:

[info] Compiling 1 Scala source to /data/app/target/scala-2.10/classes...
[success] Compiled in 2s

问题是刷新时更改不会出现在浏览器中。由于我禁用了缓存,因此没有缓存问题。如果我从主机运行应用程序,一切正常。

编辑:这是我用于使用 sbt 创建容器的 Dockerfile:

FROM dockerfile/java:oracle-java8
MAINTAINER  Jørgen Borgesen

ENV SBT_VERSION 0.13.5

# Install sbt
RUN cd /tmp && \
    wget https://dl.bintray.com/sbt/native-packages/sbt/$SBT_VERSION/sbt-$SBT_VERSION.zip && \
    unzip sbt-$SBT_VERSION.zip -d /usr/local && \
    rm sbt-$SBT_VERSION.zip

我做了更多的研究。在 docker 容器中,我像这样启动 play 应用程序:

[ root@aa1f2327d938:/data/app ]$ /usr/local/sbt/bin/sbt
[info] Loading project definition from /data/app/project
[info] Set current project to my-first-app (in build file:/data/app/)
[my-first-app] $ ~run

--- (Running the application from SBT, auto-reloading is enabled) ---

[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

(Server started, use Ctrl+D to stop and go back to the console...)

[success] Compiled in 740ms

在我的浏览器中加载页面工作正常。然后我在主机上更改我的索引文件。这会触发容器内的重新编译:

[info] Compiling 1 Scala source to /data/app/target/scala-2.10/classes...
[success] Compiled in 1s

刷新我的浏览器仍然显示初始索引文件。即使容器内的播放应用程序获取了更改。我还检查了target/scala-2.10/classes/views/html(在我的主机上,因为我在容器中运行播放应用程序并且我不确定如何将多个终端附加到它)中的编译文件。编译的文件已更改。

我做的下一件事是按Ctrl-D。根据上面打印的消息“(服务器已启动,使用 Ctrl+D 停止并返回控制台...)”,这应该让我回到 sbt 控制台。但是,这会导致以下输出:

[success] Total time: 455 s, completed Sep 25, 2014 7:40:35 AM
1. Waiting for source changes... (press enter to interrupt)

--- (Running the application from SBT, auto-reloading is enabled) ---

[info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000

(Server started, use Ctrl+D to stop and go back to the console...)

[info] play - Application started (Dev)

现在我之前所做的更改会在刷新后反映在浏览器中。

4

2 回答 2

10

我解决了这个问题(有点)。该问题并非特定于 docker 或 play 框架,而是与如何使用 JNotify 检测文件更改有关(play 使用此库)。使用本机文件系统挂钩检测更改。这些钩子在虚拟机的共享文件夹中不可用(我在 VM 机器上运行 docker 服务,因为我在 OSX 上)。这意味着自动检测文件更改的唯一方法是使用轮询策略。Play 框架在 2.3.2 及更高版本中支持。要启用,请将其添加到您的 build.sbt:

PlayKeys.playWatchService := play.sbtplugin.run.PlayWatchService.sbt(pollInterval.value)

答案取自 github 上的问题帖子:Play 2.3.2 auto reload is not working on shared folder

播放 2.4 更新:播放 2.4 重命名配置参数。这是在 2.4 中启用轮询的方法:

PlayKeys.fileWatchService := play.runsupport.FileWatchService.sbt(pollInterval.value)

感谢 philipphoffmann 对更新信息的回答。将其添加到我的答案中,为 2.3 和 2.4 提供解决方案。

更新:我刚刚为 OSX 用户发现了一个方便的工具:docker-osx-dev。它使用 rsync 使主机和虚拟文件系统保持同步。这将触发虚拟机上的文件系统更改。

于 2014-09-25T10:09:45.657 回答
3

对于播放 2.4,这将是:

PlayKeys.fileWatchService := play.runsupport.FileWatchService.sbt(pollInterval.value)
于 2015-06-13T20:11:46.947 回答