/ WEBAPP, DOCKER, SPRING BOOT

Distributing desktop webapps via Docker

Two weeks ago, we studied how to replace desktop Java apps with Java webapps. Now is the time to think about distributing such desktop webapps.

The current trend now is to use Docker. I assume readers are at least familiar with the technology. The most straightforward way is to create a WAR and deliver it inside a Tomcat image. Another option is to create a fat JAR with Tomcat embedded as per the previous post, and run it inside a image with the JRE only.

One of the deciding factors is the size of the resulting image. Interestingly enough, the second option is the best choice, as Tomcat embedded is a stripped down version of the regular distribution.

About size

To obtain the smallest image, one should favor Alpine Linux-based containers over more complete Linux distributions (such as Debian).

To slim down the image even further, use jlink, which is part of Java 9. Unfortunately, at the time of this writing, there’s no JRE 9 image available for Alpine.

Another way to shave off a few kilobytes is to replace embedded Tomcat by Jetty:

pom.xml
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>vaadin-spring-boot-starter</artifactId>
  <exclusions>
    <exclusion>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

A possible Dockerfile might look like this:

Dockerfile
FROM openjdk:8-jre-alpine

ARG JAR_FILE
ADD ${JAR_FILE} /usr/share/renamer.jar

ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/renamer.jar"]

With it, it’s possible to create an image of relatively acceptable size:

nfrankel/renamer   0.0.1-SNAPSHOT   f8ed5f177771   38 minutes ago   113MB

For Maven integration, I use the dockerfile-maven-plugin from Spotify. Here’s an example how to use it:

pom.xml
<plugin>
  <groupId>com.spotify</groupId>
  <artifactId>dockerfile-maven-plugin</artifactId>
  <version>1.4.0</version>
  <executions>
    <ecution>
      <id>default</id>
      <goals>
        <goal>build</goal>
        <goal>push</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <repository>nfrankel/renamer</repository>
    <tag>${project.version}</tag>
    <buildArgs>
      <JAR_FILE>target/${project.build.finalName}.${project.packaging}</JAR_FILE>
    </buildArgs>
  </configuration>
</plugin>

Once the image has been built, it’s trivial to launch the container:

docker run -ti -p 8080:8080 -v /tmp/foo:/tmp/foo nfrankel/renamer:0.0.1-SNAPSHOT
It’s pretty common to map the port. If the application needs to interact with the filesystem - as some (most?) desktop apps do, volumes need to be mapped as well.

At this point, all is set to launch the app. However, a new question creeps in: "How to launch a browser in Docker?"

Opening a browser on the host system is not possible from Docker. The way to go is to install a browser in the image, launch it and display it on the host through X11. However, there are a couple of drawbacks to that:

  1. It’s not trivial. On my Mac, it requires:
    • Installing dedicated software for X11 emulation (XQuartz)
    • Configuration of said software
    • Pass additional parameters for Docker to run:
      docker run -ti -e DISPLAY=192.168.1.73:0 -p 8080:8080  -v /tmp/.X11-unix:/tmp/.X11-unix nfrankel/renamer:0.0.1-SNAPSHOT
  2. It increases the size of the image a lot!

In the end, it’s better to let it out of the image and create simple multi-platform scripts to achieve the same.

The SonarQube distribution is a good example. It offers scripts for the following OS:

  • Linux 32- and 64 bits
  • OSX
  • Windows 32- and 64 bits

Conclusion

Docker is a good way to distribute servlet-embedded webapps. Yet, it comes with a not-that-good desktop integration as it’s not straightforward to interact with the host system.

The complete source code for this post can be found on Github in Maven format.
Nicolas Fränkel

Nicolas Fränkel

Nicolas Fränkel is a Software Architect with 15 years experience consulting for many different customers, in a wide range of contexts (such as telecoms, banking, insurances, large retail and public sector). Usually working on Java/Java EE and Spring technologies, but with narrower interests like Software Quality, Build Processes and Rich Internet Applications. Currently working for an eCommerce solution vendor leader. Also double as a teacher in universities and higher education schools, a trainer and triples as a book author.

Read More