编辑:有一个相关的问题是discussed on 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)
编辑:当我使用change the location of the file跟随Play文档向-Dpidfile.path=/var/run/play.pid
推荐到/var/run/play.pid时的结果相同。
Play server process ID is 7
This application is already running (Or delete /var/run/play.pid file).
当我$ 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 reference on $ docker stop
要杀死正在运行的Play服务器,只需将SIGTERM发送到进程即可正确关闭应用程序。
来自Play Framework documentation on stopping a Play application
我刚刚玩了一个Play!应用程序也遇到了这个问题 - 重启主机引起了Play!应用程序无法在其容器中启动,因为RUNNING_PID
尚未删除。
在我身上发生了戏剧! application是其容器中唯一的进程,总是具有相同的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)。
我根据答案和我在这个问题上的进一步工作,找出了一个有效的解决方法。如果我按如下方式启动容器,它们将在(非)预期停止/重启后启动。冲突的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的文件,该文件放在特定位置。
我有完全相同的问题,并通过每次容器运行时手动删除文件来解决它。为了做到这一点,我在伴随文件“start.bash”中添加了我用来从SBT dist任务的结果开始播放过程,如下所示:
找 。 -type f -name RUNNING_PID -exec rm -f {} \;
希望能帮助到你。
我对docker了解不多,但是就我测试的那样,Play并没有在停止服务器时删除RUNNING_PID
。当我在prod
模式下部署我的应用程序并尝试通过Ctrl+D
和Ctrl+C
停止它时,它不会从项目目录中删除RUNNING_PID文件,所以我不得不手动删除它。来自Play docs
通常这个(RUNNING_PID)文件放在你的播放项目的根目录中,但是建议你把它放在重启时自动清除的地方,比如
/var/run
:
因此 - 除了手动删除 - 解决方法是更改RUNNING_PID的路径,并在每次服务器通过某个脚本启动时删除它。
$ /path/to/bin/<project-name> -Dpidfile.path=/var/run/play.pid
确保该目录存在,并且运行Play应用程序的用户具有写入权限。
使用此文件,您可以使用kill命令停止应用程序,例如:
$ kill $(cat /var/run/play.pid)
你也可以尝试docker命令$ sudo docker rm --force redis
也许那会有所帮助
ctrl + c失败后我遇到了同样的问题。我通过运行docker-compose down -v
然后运行docker-compose up
解决了这个问题。 -v
选项用于指示您要删除与容器关联的卷。也许docker-compose down
就足够了。
这是一些down
选项的概述:`
码头工人组成停止
码头工人组成了
docker-compose down --volumes
docker-compose down --rmi`