无法在 Docker 上运行 JavaFX 应用超过几分钟。

10
我开发了一个应用程序,作为另一个Web应用程序的通信服务。 我没有遇到任何问题将Web应用程序“docker化”,但该服务正在证明是一场噩梦。它基于JavaFX,并且有一个属性可以在配置文件中由用户设置,使得该应用程序不初始化任何窗口、菜单、容器等。这种“无头”模式(不确定是否真正无头……)有效地将服务应用程序转换为后台服务。此外,让我先说一下,当在我的Windows 10机器上运行该应用程序时,它绝对完美无缺,并且我已经在其他几台机器上部署了它(所有机器都未进行“docker化”),也没有出现任何问题。
这是我想出的Dockerfile:
FROM openjdk:13.0.1-slim
RUN apt-get update && apt-get install libgtk-3-0 libglu1-mesa -y && apt-get update
VOLUME /tmp
ADD Some_Service-0.0.1-SNAPSHOT.jar Some_Service-0.0.1-SNAPSHOT.jar
ADD lib lib
ADD config.properties config.properties
ENTRYPOINT ["java", "--module-path", "lib/javafx-sdk-13", "-jar", "Some_Service-0.0.1-SNAPSHOT.jar"]

I then use this command to build the container :

docker run -t --name Some_Service -e DISPLAY=192.168.1.71:0.0 -e SERVICE_HOME= --link mySQLMD:mysql some_service

假设我的电脑上正在运行VcXsrv,该应用程序可以正确启动,但在首次启动时会发出以下警告:
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
Prism-ES2 Error : GL_VERSION (major.minor) = 1.4

问题在于它只能工作大约2分钟。最终容器出现了这个错误并崩溃:
Gdk-Message: 15:28:54.770: java: Fatal IO error 11 (Resource temporarily unavailable) on X server 192.168.1.71:0.0.

我理解最初的信息是由于容器没有NVidia驱动程序,但回退到软件管道似乎运行良好。老实说,我不知道致命的IO错误可能是由什么引起的。我已经在运行docker的不同主机上尝试过,并且发生了相同的问题。

有任何修复这个问题的想法吗?更好的是,有任何想法如何使JavaFX应用程序真正无头,甚至不需要初始化任何这些东西?当运行无头时,我使用JavaFX的任务等,因此不能不使用它...


尝试将主机的Xserver绑定到容器运行时(即 -v /tmp/.X11-unix:/tmp/.X11-unix)中了吗?应用程序尝试连接Xserver表明它不是“无头”的,需要检查实现。 - masseyb
尝试使用GPU支持运行。“docker run -t --name Some_Service --gpus all -e DISPLAY=192.168.1.71:0.0 -e SERVICE_HOME= --link mySQLMD:mysql some_service” - arshpreet
@arshpreet 这个给我报错了:守护进程的错误响应:无法选择具有能力的设备驱动程序“”:[[gpu]]。 - Martin
@masseyb 我在Windows机器上运行Docker。 - Martin
1个回答

4

在您的容器中安装Xvfb以创建虚拟屏幕。 更改Docker文件:

FROM openjdk:13.0.1-slim
RUN apt-get update && apt-get install libgtk-3-0 libglu1-mesa xvfb -y && 
apt-get update
VOLUME /tmp
ADD Some_Service-0.0.1-SNAPSHOT.jar Some_Service-0.0.1-SNAPSHOT.jar
ADD lib lib
ADD config.properties config.properties
apt-get install xvfb
ENV DISPLAY=:99
ADD run.sh /run.sh
RUN chmod a+x /run.sh
CMD /run.sh 

在项目文件夹中添加一个新的bash脚本,并将其命名为 "run.sh"。
run.sh:
#!/bin/bash
#remove old 
rm /tmp/.X99-lock #needed when docker container is restarted
Xvfb :99 -screen 0 640x480x8 -nolisten tcp &
java --module-path lib/javafx-sdk-13 -jar Some_Service-0.0.1-SNAPSHOT.jar

不要忘记从您的docker运行命令中删除-e DISPLAY=192.168.1.71:0.0

你能向我展示如何将入口点从java -jar命令更改为包含java -jar语句和xvfb命令的命令吗? - Martin
我尝试了这里描述的方法:https://success.docker.com/article/use-a-script-to-initialize-stateful-container-data。但是,这给了我以下错误:standard_init_linux.go:211: exec user process caused "exec format error"。 - Martin
抱歉,我对Unix还不是很熟练 :( 当我执行docker run命令时,现在出现了这个错误:/bin/sh: 1: /run.sh: not found。 - Martin
我曾认为Docker不能将run.sh添加到镜像中。你可以将“CMD /run.sh”更改为ENTRYPOINT ["/run.sh"]。这两种方式对我都可以正常运行。 - leachim742
我在另一篇帖子中找到了这个答案,可能就是这个原因吧?这是因为你在Windows中以\r\n的方式从Github检出文件。你需要手动将所有.sh/.bash文件的EOL样式转换为\n。 - Martin
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接