java.awt.AWTError : Can't connect to X11 window server using ':0' as the value of the DISPLAY variable 错误

标签 java docker dockerfile x11-forwarding

我一直在尝试在 Docker 内的 Ubuntu VM 上运行一个基于 Java AWT 的应用程序。该应用程序非常简单,它通过 Eclipse 在 Windows 上完美运行。它只是打开一个窗口并打印 hello world!。事实上,当我将 jar 文件导出到在我的 Windows 主机上运行的 Ubuntu VM 时,当我通过 “java -jar JFrameDocker.jar” 运行 jar 文件时,也会给我与 Windows 相同的输出.

然而,当我尝试在 docker 中运行它时,情况就不一样了。我在 Dockerfile 中指定的指令执行时没有任何错误,但是当我运行应用程序时它会抛出 “java.awt.AWTError:无法使用‘:0’作为 DISPLAY 变量的值连接到 X11 窗口服务器”。相信我,我已经尝试了很多次来解决它,但直到现在都没有运气。 比如多次设置 DISPLAY 变量值,使用 xterm 和 xeyes 启动 X 服务器,浏览我在 Web 上找到的所有可能的文章。但是这里似乎没有任何作用。我在这里提供了我所有的文件,可以让你更好地理解我的问题。 顺便this没有回答我的问题,因为即使在进行更改后也会抛出相同的错误。

这是我的 java 文件。

package com.etp;
import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class JFrameDockerTest {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        JLabel lable = new JLabel("Hello World");
        panel.setLayout( new FlowLayout() );  
        frame.add(panel);
        panel.add(lable);
        frame.setVisible(true);
        frame.setSize(800, 600);
    }

}

这是我的 Dockerfile:

FROM java:8
ENV DISPLAY :0
ADD JFrameDocker.jar JFrameDocker.jar
CMD ["java","-jar", "JFrameDocker.jar"]

我使用下面的 docker 命令来构建镜像并运行它。

Docker 构建:sudo docker build -t jframedocker 。

Docker 运行:sudo docker run jframedocker

Output Without Error Screenshot: (Without Docker)

使用 Docker 输出:

etp@etp-VirtualBox:~/Downloads/JFrameDocker$ sudo docker run jframedocker
Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.awt.AWTError: Can't connect to X11 window server using ':0' as the value of the DISPLAY variable.
    at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
    at sun.awt.X11GraphicsEnvironment.access$200(X11GraphicsEnvironment.java:65)
    at sun.awt.X11GraphicsEnvironment$1.run(X11GraphicsEnvironment.java:115)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:74)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at java.awt.GraphicsEnvironment.createGE(GraphicsEnvironment.java:103)
    at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:82)
    at java.awt.Window.initGC(Window.java:475)
    at java.awt.Window.init(Window.java:495)
    at java.awt.Window.<init>(Window.java:537)
    at java.awt.Frame.<init>(Frame.java:420)
    at java.awt.Frame.<init>(Frame.java:385)
    at javax.swing.JFrame.<init>(JFrame.java:189)
    at com.etp.JFrameDockerTest.main(JFrameDockerTest.java:12)
    ... 5 more

最佳答案

您正在使用 java:8 基本图像,它很可能不提供图形环境。

您可以将 ubuntu:18.04 基础镜像与手动安装的 openjdk-11-jdkxvfb 包一起使用。 xvfb-run命令将负责设置虚拟 X 服务器环境:

xvfb-run sets up an X authority file (or uses an existing user-specified one), writes a cookie to it (see xauth(1x)) and then starts the Xvfb X server as a background process. The process ID of Xvfb is stored for later use. The specified command is then run using the X display corresponding to the Xvfb server just started and the X authority file created earlier.

Dockerfile

FROM ubuntu:18.04
RUN apt-get update -y && apt-get upgrade -y && apt-get install -y openjdk-11-jdk xvfb 
ADD JFrameDocker.java MANIFEST.mf ./
RUN javac JFrameDocker.java
RUN jar cfm JFrameDocker.jar MANIFEST.mf JFrameDocker.class 
RUN xvfb-run java -jar JFrameDocker.jar

JFrameDocker.java

import java.awt.FlowLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class JFrameDocker {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        JLabel lable = new JLabel("Hello World");
        panel.setLayout(new FlowLayout());  
        frame.add(panel);
        panel.add(lable);
        frame.setSize(800, 600);
        frame.setVisible(true);
        System.out.println("Up and running");
    }

}

MANIFEST.mf

Manifest-Version: 1.0
Main-Class: JFrameDocker

关于java.awt.AWTError : Can't connect to X11 window server using ':0' as the value of the DISPLAY variable 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55220901/

相关文章:

java - 使用 RestTemplate 调用 API 时如何捕获超时异常

powershell - 某些Docker命令在Windows Powershell ISE中不起作用,但在其他命令行工具中起作用

docker - 扩展现有的Docker镜像

go - 用于 Go 的 Docker Remote API v1.24 库?

java - 如何为 Ubuntu 安装 Jpcap

java - 在 Java 中引用匿名内部类中封闭类的非最终字段

Java 射弹角度

带有 postgresql 和 redis 的 Docker 镜像

docker - 使用 kubernetes 时找不到 Package.json 文件

docker - 将本地环境变量传递给docker