【问题标题】:java.awt.AWTError: Can't connect to X11 window server using ':0' as the value of the DISPLAY variablejava.awt.AWTError: Can't connect to X11 window server using ':0' 作为 DISPLAY 变量的值
【发布时间】:2019-08-08 19:03:23
【问题描述】:

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

但是,当我尝试在 docker 中运行它时,情况就不一样了。我在 Dockerfile 中指定的指令执行时没有任何错误,但是当我运行应用程序时它会抛出 “java.awt.AWTError: Can't connect to X11 window server using ':0' as the value of DISPLAY variable” .相信我,伙计们,我已经尝试了很多次来解决它,但直到现在都没有运气。 就像多次设置 DISPLAY 变量值,使用 xterm 和 xeyes 启动 X 服务器,浏览我在网上找到的所有可能的文章。但这里似乎没有任何效果。我在这里提供了我的所有文件,可以让您更好地了解我的问题。 顺便说一句,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 docker dockerfile x11-forwarding


【解决方案1】:

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

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

xvfb-run 设置一个 X 授权文件(或使用现有的用户指定文件),向其中写入一个 cookie(参见 xauth(1x)),然后启动 Xvfb X 服务器一个后台进程。存储 Xvfb 的进程 ID 以供以后使用。然后使用与刚刚启动的 Xvfb 服务器对应的 X 显示和之前创建的 X 权限文件运行指定的命令。

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

【讨论】:

  • 我尝试了您的建议,但导致以下错误 docker:来自守护进程的错误响应:OCI 运行时创建失败:container_linux.go:344:启动容器进程导致“exec:\”java\”:可执行文件在 $PATH 中找不到文件”:未知。
  • @SoumyaranjanPani 因为它在容器中运行,而不是在主机系统中。您必须配置 X 转发才能看到容器屏幕。
  • 好的。我明白。您能否指导我如何配置 X 转发,以便我可以在容器屏幕中看到输出。
  • 事实上,我在 ssh_configsshd_config 文件中配置了 X11 转发,但即使它不打印statement System.out.println("启动并运行");
  • ssh_config里面有关于X11转发的三个参数,我设置的值如下ForwardAgent yes ForwardX11 yes ForwardX11Trusted 是 并且在 sshd_config X11Forwarding 是 X11UseForwarding 是 X11DisplayOffset 10 X11UseLocalhost是的
猜你喜欢
  • 2020-10-25
  • 1970-01-01
  • 2014-07-31
  • 1970-01-01
  • 2015-11-01
  • 2020-02-21
  • 2021-06-25
  • 2013-09-12
  • 1970-01-01
相关资源
最近更新 更多