【问题标题】:Getting a javaFX 11 app to work on docker让 javaFX 11 应用程序在 docker 上运行
【发布时间】:2019-11-21 11:18:54
【问题描述】:

我正在尝试让一个可以在我的机器上完美运行的应用程序在 docker 上运行,这是我的 docker 文件:

FROM openjdk:11-jre-slim
VOLUME /tmp
ADD someJar.jar someJar.jar
ADD lib lib
ADD config.properties config.properties
ENTRYPOINT ["java", "-javaagent:lib/aspectjweaver-1.9.2.jar", 
    "-javaagent:lib/spring-instrument-5.1.6.RELEASE.jar", "--module-path", 
    "lib/javafx-sdk-11.0.2", "--add-modules=javafx.controls", "- 
    Dprism.verbose=true", "-jar","someJar.jar"]

我还尝试将它基于 alpine openjdk11 版本,结果相同:

FROM adoptopenjdk/openjdk11:alpine
VOLUME /tmp
RUN apk update && apk add libx11 mesa-gl gtk+3.0 && apk update
ADD someJar.jar someJar.jar
ADD lib lib
ADD config.properties config.properties
ENTRYPOINT ["java", "-javaagent:lib/aspectjweaver-1.9.2.jar", "-javaagent:lib/spring-instrument-5.1.6.RELEASE.jar", "--module-path", "lib", "--add-modules=javafx.controls", "-Dprism.verbose=true", "-jar","someJar.jar"]

lib 文件夹包含 openJFX 运行时的 linux 风格(.so 文件和 .jar 文件)。我正在使用与 Windows 等效的 openJDK 运行时在 Windows 机器上开发它,它运行良好。运行容器时,我得到以下输出:

Prism pipeline init order: es2 sw
Using Double Precision Marlin Rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.es2.ES2Pipeline
Loading ES2 native library ... prism_es2
GraphicsPipeline.createPipeline failed for com.sun.prism.es2.ES2Pipeline
java.lang.UnsatisfiedLinkError: no prism_es2 in java.library.path: [/usr/java/packages/lib, /usr/lib/x86_64-linux-gnu/jni, /lib/x86_64-linux-gnu, /usr/lib/x86_64-linux-gnu, /usr/lib/jni, /lib, /usr/lib]
    at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2660)
    at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:829)
    at java.base/java.lang.System.loadLibrary(System.java:1867)
    at javafx.graphics/com.sun.glass.utils.NativeLibLoader.loadLibraryInternal(NativeLibLoader.java:150)
    at javafx.graphics/com.sun.glass.utils.NativeLibLoader.loadLibrary(NativeLibLoader.java:52)
    at javafx.graphics/com.sun.prism.es2.ES2Pipeline.lambda$static$0(ES2Pipeline.java:68)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.prism.es2.ES2Pipeline.<clinit>(ES2Pipeline.java:50)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:315)
    at javafx.graphics/com.sun.prism.GraphicsPipeline.createPipeline(GraphicsPipeline.java:187)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.init(QuantumRenderer.java:91)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:124)
    at java.base/java.lang.Thread.run(Thread.java:834)
*** Fallback to Prism SW pipeline
Prism pipeline name = com.sun.prism.sw.SWPipeline
(X) Got class = class com.sun.prism.sw.SWPipeline
Initialized prism pipeline: com.sun.prism.sw.SWPipeline
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:47)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:86)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: java.lang.UnsupportedOperationException: Unable to open DISPLAY
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$new$6(GtkApplication.java:173)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.<init>(GtkApplication.java:171)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkPlatformFactory.createApplication(GtkPlatformFactory.java:41)
    at javafx.graphics/com.sun.glass.ui.Application.run(Application.java:144)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:258)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:269)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:834)

知道如何让基于 OpenJFX11 的 Java 应用程序在 Docker 中工作吗?

******更新******

我在这方面取得了一些进展。我发现将我的 openJFX 运行时文件直接放在我的 lib 文件夹中使它进步了一点。新的错误变成了这样:

ImportError: libGL.so.1: cannot open shared object file: No such file or directory

经过一番研究,我在我的 dockerfile 中添加了这个 RUN 命令:

RUN apt-get update && apt-get install libgl1-mesa-glx -y

这给了我一个新的堆栈跟踪:

Prism pipeline init order: es2 sw
Using Double Precision Marlin Rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.es2.ES2Pipeline
Loading ES2 native library ... prism_es2
    succeeded.
GLFactory using com.sun.prism.es2.X11GLFactory
(X) Got class = class com.sun.prism.es2.ES2Pipeline
GraphicsPipeline.createPipeline: error initializing pipeline 
com.sun.prism.es2.ES2Pipeline
*** Fallback to Prism SW pipeline
Prism pipeline name = com.sun.prism.sw.SWPipeline
(X) Got class = class com.sun.prism.sw.SWPipeline
Initialized prism pipeline: com.sun.prism.sw.SWPipeline
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:47)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:86)
    at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
    at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
Caused by: java.lang.UnsupportedOperationException: Unable to open DISPLAY
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.lambda$new$6(GtkApplication.java:173)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkApplication.<init>(GtkApplication.java:171)
    at javafx.graphics/com.sun.glass.ui.gtk.GtkPlatformFactory.createApplication(GtkPlatformFactory.java:41)
    at javafx.graphics/com.sun.glass.ui.Application.run(Application.java:144)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.startup(QuantumToolkit.java:258)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:269)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.startup(PlatformImpl.java:158)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.startToolkit(LauncherImpl.java:658)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:678)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:834)

******另一个更新******

挖掘 GtkApplication.class 文件中的 JavaFX 代码,这是失败的部分:

int libraryToLoad = _queryLibrary(gtkVersion, gtkVersionVerbose);

AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
        if (libraryToLoad == QUERY_NO_DISPLAY) {
            throw new UnsupportedOperationException("Unable to open DISPLAY");
        } else if (libraryToLoad == QUERY_USE_CURRENT) {
            if (gtkVersionVerbose) {
                System.out.println("Glass GTK library to load is already loaded");
            }
        } else if (libraryToLoad == QUERY_LOAD_GTK2) {
            if (gtkVersionVerbose) {
                System.out.println("Glass GTK library to load is glassgtk2");
            }
            NativeLibLoader.loadLibrary("glassgtk2");
        } else if (libraryToLoad == QUERY_LOAD_GTK3) {
            if (gtkVersionVerbose) {
                System.out.println("Glass GTK library to load is glassgtk3");
            }
            NativeLibLoader.loadLibrary("glassgtk3");
        } else {
            throw new UnsupportedOperationException("Internal Error");
        }
        return null;
    });

我是否缺少图书馆或其他东西?

...帮助?

谢谢

【问题讨论】:

  • 阅读我能找到的关于此错误的所有内容,尝试将 -e DISPLAY=host.docker.internal:0 添加到 docker run 命令中,但仍然收到相同的错误。
  • javaFX 的负载似乎有问题,也许你需要对此进行更好的调查
  • 您正在尝试在 Linux 容器中运行带有 GUI 的 Java 应用程序。据我所知,容器无头运行,因此无法显示用户界面。在您的评论中,您尝试向 docker 提供当前显示以供使用,但老实说,我怀疑这是否适用于 Linux/Windows 边界。我很高兴被证明是错误的,但我认为 Docker 不可能在 Windows 主机上显示 Linux GUI。
  • @cello 我觉得你可以通过使用 XServer 来完成这项工作。

标签: java docker javafx java-11 openjfx


【解决方案1】:

我终于让它工作了!我必须在我的 Windows 主机上安装 VcXsrv 并将其添加到 docker run 命令:

-e DISPLAY=MY IP ADDRESS:0.0

我的应用现在可以正常启动并在实际开始 Spring 初始化之前输出以下内容:

Prism pipeline init order: es2 sw
Using Double Precision Marlin Rasterizer
Using dirty region optimizations
Not using texture mask for primitives
Not forcing power of 2 sizes for textures
Using hardware CLAMP_TO_ZERO mode
Opting in for HiDPI pixel scaling
Prism pipeline name = com.sun.prism.es2.ES2Pipeline
Loading ES2 native library ... prism_es2
    succeeded.
GLFactory using com.sun.prism.es2.X11GLFactory
MESA-LOADER: failed to open swrast (search paths /usr/lib/xorg/modules/dri)
libGL error: failed to load driver: swrast
Prism-ES2 Error : GL_VERSION (major.minor) = 1.4
(X) Got class = class com.sun.prism.es2.ES2Pipeline
GraphicsPipeline.createPipeline: error initializing pipeline com.sun.prism.es2.ES2Pipeline
*** Fallback to Prism SW pipeline
Prism pipeline name = com.sun.prism.sw.SWPipeline
(X) Got class = class com.sun.prism.sw.SWPipeline
Initialized prism pipeline: com.sun.prism.sw.SWPipeline
MESA-LOADER: failed to open swrast (search paths /usr/lib/xorg/modules/dri)
libGL error: failed to load driver: swrast
vsync: true vpipe: false 

我仍然会尝试解决一些错误,但它实际上现在就开始了!

按要求完整的 dockerfile,我仍在处理导致它回退到 prism 管道的错误,稍后会更新:

FROM adoptopenjdk/openjdk11:alpine
VOLUME /tmp
RUN apk update && apk add libx11 mesa-gl gtk+3.0 mesa-dri-swrast mesa-demos 
    && apk update
ADD someJar.jar someJar.jar
ADD lib lib
ADD config.properties config.properties
ENTRYPOINT ["java", "-javaagent:lib/aspectjweaver-1.9.2.jar", "-javaagent:lib/spring-instrument-5.1.6.RELEASE.jar", "--module-path", "lib", "--add-modules=javafx.controls", "-Dprism.verbose=true", "-Djava.awt.headless=true", "-jar","someJar.jar"]

******最终设置******

我深入研究了 libGL 错误,让 ES2 管道工作的麻烦甚至不值得我的需要。这将涉及与 Nvidia 和 CUDA 驱动程序混淆,并且完全没用,因为无论如何我的应用程序只是一个后台服务。这是使一切正常的最终设置:

Dockerfile(切换回 openjdk 以与我的其他应用程序保持一致,并找出要安装的最少软件包)

FROM openjdk:11-jre-slim
RUN apt-get update && apt-get install libgtk-3-0 libglu1-mesa -y && apt-get update
VOLUME /tmp
ADD someJar.jar someJar.jar
ADD lib lib
ADD config.properties config.properties
ENTRYPOINT ["java", "-javaagent:lib/aspectjweaver-1.9.2.jar", "-javaagent:lib/spring-instrument-5.1.6.RELEASE.jar", "--module-path", "lib/javafx-sdk-11.0.2", "-jar", "someJar.jar"]

Docker 构建命令

docker build -f Dockerfile -t some_service .

Docker 运行命令

docker run -t --name Some_Service -e DISPLAY=MY IP:0.0 -e SOME_VARIABLE= --link mySQLSRV:mysql some_service

希望这对某人有所帮助,这花了我几天的时间才开始工作!

【讨论】:

  • 不错的技巧,不过拥有完整的 DockerFile 就好了
  • 添加了完整的 dockerfile
  • 不幸的是,这只工作了几分钟,然后不知从哪里我得到了这个错误:32mMessage:java:Fatal IO error 11(资源暂时不可用)在 X 服务器 xxx.xxx.xxx.xxx:0.0 .有什么想法吗?!
  • 似乎相关(库中的 32/64 位混合)stackoverflow.com/questions/25790890/xio-fatal-io-error-11 你可以在 linux 主机或 vm 上尝试
  • 遗憾的是,我仍然收到 DISPLAY 错误 $ docker run -i -t apps:latest -e DISPLAY=x.my.ip.x:0.0 线程“main”中的异常 java.lang.UnsupportedOperationException:无法在 com.sun.glass.ui.gtk.GtkApplication.lambda$new$6(GtkApplication.java:173) 打开 DISPLAY .... DISPLAY env var 似乎没有解决我的问题
猜你喜欢
  • 2020-06-19
  • 2018-11-22
  • 2020-06-19
  • 2020-03-23
  • 2022-08-22
  • 1970-01-01
  • 1970-01-01
  • 2017-12-03
  • 2021-07-01
相关资源
最近更新 更多