我一直在尝试在 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-jdk
和 xvfb
包一起使用。 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/