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

Soumyaranjan Pani picture Soumyaranjan Pani · Mar 18, 2019 · Viewed 11.5k times · Source

I have been trying to run a Java AWT based application on an Ubuntu VM inside Docker. The application is a very simple one and it flawlessly runs on Windows through Eclipse. It simply opens up a window and prints hello world!. In fact when I export the jar file in to an Ubuntu VM that is running on my Windows host also gives me the same output as Windows when I run the jar file through “java -jar JFrameDocker.jar”.

However the story is not same when I try to run it inside docker. The instructions that I have specified in the Dockerfile executes without any error but when I run the application it throws “java.awt.AWTError: Can't connect to X11 window server using ':0' as the value of the DISPLAY variable” . Trust me guys, I have tried many a times to resolve it but no luck till now. Like setting the DISPLAY variable value multiple times, starting X server using xterm and xeyes, going through every possible article that I found on the Web. But nothing seems to be working here. I am providing all my files here that could get you a better understanding of my problem. By the way this doesn't answer my question as same error is being thrown even after making the changes.

This is my java file.

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);
    }

}

This is my Dockerfile:

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

I have used below docker commands to build image and run it.

Docker Build : sudo docker build -t jframedocker .

Docker Run : sudo docker run jframedocker

Output Without Error Screenshot: (Without Docker)

Output with 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

Answer

Karol Dowbecki picture Karol Dowbecki · Mar 18, 2019

You are using java:8 base image which most likely doesn't provide a graphical environment.

You can use ubuntu:18.04 base image with manually installed openjdk-11-jdk and xvfb packages. The xvfb-run command will take care of setting up the virtual X Server environment:

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