重新启动 Play 应用程序 Docker 容器会导致“此应用程序已在运行” - RUNNING_PID不会被删除

编辑:Github上有一个相关的问题正在讨论,但在另一种部署模式下(Typesafe Activator UI而不是Docker)。

我试图模拟系统重启,以验证Docker重启策略,该策略声明能够以正确的顺序重新运行容器。

我有一个用Java编写的Play框架应用程序。

Dockerfile 看起来像这样:

FROM ubuntu:14.04
#
#  [Java8, ...]
#
RUN chmod +x /opt/bin/playapp
CMD ["/bin/bash"]

我使用.$ docker run --restart=always -d --name playappcontainer "./opt/bin/playapp"

当我和控制台告诉我:$ service docker stop && service docker restart$ docker attach playappcontainer

Play server process ID is 7
This application is already running (Or delete /opt/RUNNING_PID file)

编辑:当我按照 Play 文档的建议将文件的位置更改为 /var/run/play.pid with .-Dpidfile.path=/var/run/play.pid

Play server process ID is 7
This application is already running (Or delete /var/run/play.pid file).

那么:为什么当 docker 守护程序停止、重新启动并重新启动以前运行的容器时,包含 RUNNING_PID 的文件没有被删除?


当我,它告诉我:$ docker inspect playappcontainer

"State": {
    "ExitCode": 255,
    "FinishedAt": "2015-02-05T17:52:39.150013995Z",
    "Paused": false,
    "Pid": 0,
    "Restarting": true,
    "Running": true,
    "StartedAt": "2015-02-05T17:52:38.479446993Z"
},

虽然:

容器内的主要进程将收到 SIGTERM,并在宽限期后接收 SIGKILL。

Docker 引用上 $ docker stop

要终止正在运行的 Play 服务器,只需向进程发送 SIGTERM 即可正确关闭应用程序。

Play 框架文档中停止 Play 应用程序


答案 1

我刚刚玩了一出戏!应用程序,并且还遇到了此问题 - 重新启动主机导致播放!应用程序无法在其容器中启动,因为尚未删除。RUNNING_PID

我突然想到,就像戏剧一样!应用程序是其容器中唯一的进程,始终具有相同的PID,并由Docker负责,该文件(据我所知)实际上并不需要。RUNNING_PID

因此,我通过放置pidfile.path/dev/null

javaOptions in Universal ++= Seq(
  "-Dpidfile.path=/dev/null"
)

在我项目的 build.sbt 中。它的工作原理 - 我可以重新启动主机(和容器)和我的Play!应用程序启动正常。

这种方法对我的吸引力在于,它不需要改变sbt-native-packager生成图像本身的方式,只需要改变应用程序在其中运行的方式。

这适用于 sbt-native-packager 1.0.0-RC2 及更高版本(因为该版本包含 https://github.com/sbt/sbt-native-packager/pull/510)。


答案 2

我根据答案和我对这个问题的进一步工作整理出了一个可行的解决方法。如果我按如下方式启动容器,它们将在(非)预期的停止/重新启动后启动。冲突的RUNNING_PID文件不会阻止容器重新启动。

$ sudo docker run --restart=on-failure:5 -d \
--name container my_/container:latest \
sh -c "rm -f /var/run/play.pid && ./opt/bin/start \
-Dpidfile.path=/var/run/play.pid"

它所做的是删除包含进程ID的文件,该文件在运行二进制文件之前每次都使用一个选项放在特定位置。


推荐