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

Ste*_*ven 16 java playframework playframework-2.0 docker playframework-2.3

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

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

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

Dockerfile看起来像这样:

FROM ubuntu:14.04
#
#  [Java8, ...]
#
RUN chmod +x /opt/bin/playapp
CMD ["/bin/bash"]
Run Code Online (Sandbox Code Playgroud)

我开始使用它$ 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)
Run Code Online (Sandbox Code Playgroud)

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

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

那么:为什么当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"
},
Run Code Online (Sandbox Code Playgroud)

虽然:

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

来自Docker参考$ docker stop

要杀死正在运行的Play服务器,只需将SIGTERM发送到进程即可正确关闭应用程序.

Play Framework文档中停止Play应用程序

dhp*_*ott 27

我刚刚玩了一个Play!应用程序也遇到了这个问题 - 重启主机引起了Play!应用程序无法在其容器中启动,因为RUNNING_PID尚未删除.

在我身上发生了戏剧!应用程序是其容器中唯一的进程,始终具有相同的PID,并由Docker负责,该RUNNING_PID文件(据我所知)实际上并不需要.

因此我通过放置pidfile.path来覆盖/dev/null

javaOptions in Universal ++= Seq(
  "-Dpidfile.path=/dev/null"
)
Run Code Online (Sandbox Code Playgroud)

在我的项目的build.sbt中.它的工作原理 - 我可以重启主机(和容器)和我的Play!申请开始很好.

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

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


Ste*_*ven 5

我根据答案和我在这个问题上的进一步工作,找出了一个有效的解决方法.如果我按如下方式启动容器,它们将在(非)预期停止/重启后启动.冲突的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"
Run Code Online (Sandbox Code Playgroud)

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