How Do I Run a Java App with a GUI in Docker?

Docker is best suited for running services vs. applications that have GUIs. However, it is possible to run applications that have X11 based GUIs on Docker using x11vnc. It is a rather complex topic.

Let's start with the basics,

mkdir apps  
cat <<\EOF > apps/  
import javax.swing.*;        

public class HelloWorldSwing {  
    private static void createAndShowGUI() {
        JFrame frame = new JFrame("HelloWorldSwing");
        JLabel label = new JLabel("<html><div style='font-size: 100pt'>Hello World</div></html>");
        label.putClientProperty("JComponent.sizeVariant", "large");

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {

OK, we have a Java program. Now we need to compile it.

docker run -v$(pwd)/apps:/apps --name openjdk:7-jdk-alpine javac /apps/Hello/  

Now for the fun part. Let's bring up a Docker container running x11vnc and Java 8. We'll use Java 8 from Azul Systems vs. OpenJDK.

First we need to create some files:

mkdir profile.d  
cat <<\EOF > profile.d/  

export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/X11R6/bin:/usr/bin/X11:/usr/openwin/bin:/usr/dt/bin:/opt/kde4/bin:/opt/kde3/bin:/opt/gnome/bin:/usr/bin:/bin:/usr/sfw/bin:/usr/local/bin:/usr/lib/jvm/zulu-8-amd64/jre/bin  
cat <<\EOF > xsession  
# ~/.Xclients, start my programs.

xterm -ls -geometry 190x70+80+30 &

echo Starting Window Manager...

exec lwm >> ~/.lwm-errors 2>&1

# eof
cat <<\EOF > Dockerfile  
FROM debian:jessie-slim

RUN     apt-key adv --keyserver hkp:// --recv-keys 0x219BD9C9  
RUN     echo "deb stable  main" >> /etc/apt/sources.list.d/zulu.list  
RUN     apt-get -qq update  
RUN    apt-get install -y vim net-tools netcat  
RUN    apt-get install -y x11vnc xvfb  
RUN    apt-get install -y lwm  
RUN    apt-get -yq install zulu-8; true

RUN    mkdir /root/.vnc

COPY    xsession /root/.xsession  
RUN    chmod +x /root/.xsession

ADD    profile.d /etc/profile.d

EXPOSE  5900  
cat <<\EOF > rungui  
docker build -t debian:gui --build-arg REBUILD=${RANDOM} . 2>&1 | tee build.out

#docker rm -f
docker run -d -p 3000:3000 -p 3000:3000/udp -p 5900:5900 -v$(pwd)/apps:/root/apps --name debian:gui init  
docker exec -it su - -c 'x11vnc -forever -nopw -create'  
chmod +x rungui  

Let's start the Docker container where the app lives:


We'll need a VNC viewer. I like this one:

For testing, we can just disable all the security and passwords in the VNC viewer. Then connect to the Docker container. Note: you must use the IP address of the host running the Docker engine. If this is a VM, the network interface must be bridged or port forwarding of 5900 must be used.

At this point you will have a shell running in an xterm. Just execute the program using the java command:

cd apps/Hello  
java HelloWorldSwing