Spring Boot Thin Launcher and Docker
Tags: springboot, docker, java
Published: 2018-10-02 12:44:32

---
title: Spring Boot Thin Launcher and Docker
published: true
description: 
tags: #springboot #docker #java
---

## Spring Boot Thin Launcher

Yesterday, I played with the Spring Boot Startup Bench.

{% link https://dev.to/bufferings/started-enjoying-spring-boot-startup-bench-1ahj %}

and noticed it uses Spring Boot Thin Launcher. So today, I played with the Thin Launcher, which enables to create a thin jar.

https://github.com/dsyer/spring-boot-thin-launcher

## My Source Code

is here:

https://github.com/bufferings/spring-boot-thin-sandbox

There are 3 directories.

* demo-fat: Normal SpringBoot app.
* demo-thin: Thin app.
* demo-thin-docker: Thin app with docker.

## demo-fat

This is just a simple spring boot app with web, though it has no page.

```sh
❯ cd demo-fat
❯ ./mvnw clean package
❯ ls -ahl target/demo-fat-0.0.1-SNAPSHOT.jar
-rw-rw-r - 1 bufferings bufferings 16M Sep 30 22:16 target/demo-fat-0.0.1-SNAPSHOT.jar
```

The size is 16MB.

```sh
❯ java -jar target/demo-fat-0.0.1-SNAPSHOT.jar
…
2018–09–30 22:29:04.617 INFO 32639 - - [ main] com.example.demo.DemoApplication : Started DemoApplication in 3.852 seconds (JVM running for 4.464)
…
```

## demo-thin

This is also a simple spring boot app, but with Spring Boot Thin Launcher.

```sh
❯ cd demo-thin
❯ ./mvnw clean package
❯ ls -ahl target/demo-thin-0.0.1-SNAPSHOT.jar
-rw-rw-r - 1 bufferings bufferings 11K Sep 30 22:24 target/demo-thin-0.0.1-SNAPSHOT.jar
```

It's only 11KB. It downloads a launcher and libraries on startup, but actually it uses .m2 directory so it doesn't take so long.

```sh
❯ java -jar target/demo-thin-0.0.1-SNAPSHOT.jar
…
2018–09–30 22:30:51.689 INFO 1303 - - [ main] com.example.demo.DemoApplication : Started DemoApplication in 3.012 seconds (JVM running for 4.987)
…
```

## demo-thin-docker

This is a thin app with Docker.

```sh
❯ cd demo-thin-docker
❯ ./mvnw clean package
❯ docker build -t demo-thin-docker .
```

This takes time to download all the dependencies.

```sh
❯ docker run -p 8080:8080 demo-thin-docker - thin.debug=true - thin.offline=true
…
2018–09–30 13:42:32.978 INFO 1 - - [ main] com.example.demo.DemoApplication : Started DemoApplication in 3.437 seconds (JVM running for 5.804)
…
```

## The Dockerfile

is as follows:

```sh
FROM openjdk:11-jdk-slim
COPY docker/spring-boot-thin-wrapper-1.0.15.RELEASE.jar /thin/wrapper.jar
COPY pom.xml /thin/pom.xml
WORKDIR /thin
RUN jar cvf pom.jar pom.xml
RUN java -jar wrapper.jar \
     --thin.archive=/thin/pom.jar \
     --thin.dryrun=true \
     --thin.debug=true

FROM openjdk:11-jre-slim
COPY --from=0 /root/.m2 /root/.m2
COPY target/demo-thin-docker-0.0.1-SNAPSHOT.jar /app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
```

### FROM

```sh
FROM openjdk:11-jdk-slim
```

There's no reason to use Java 11, we can use the older version :)

### COPY wrapper.jar

```sh
COPY docker/spring-boot-thin-wrapper-1.0.15.RELEASE.jar /thin/wrapper.jar
```

I wanted to create a docker layer for the libraries. So I downloaded the wrapper.jar and put it in the repository.

It has a feature of dry-run which doesn't run the main class but just download the libraries into .m2 repository.

### COPY pom.xml

```sh
COPY pom.xml /thin/pom.xml
WORKDIR /thin
RUN jar cvf pom.jar pom.xml
```

To create the docker layer, copy the project pom.xml. The wrapper.jar can load a pom.xml in jar file. So I create a jar file which has only the pom file.

### dry-run

```sh
RUN java -jar wrapper.jar \
     --thin.archive=/thin/pom.jar \
     --thin.dryrun=true \
     --thin.debug=true
```

Then, execute wrapper jar with the pom.jar in a dry-run mode. If you want to know more detail, you can set `--thin.trace=true`.

Then all the dependencies of the pom.xml are downloaded into the `/root/.m2` directory.

### COPY .m2

```sh
FROM openjdk:11-jre-slim
COPY --from=0 /root/.m2 /root/.m2
```

I used the multi stage build, because I don't need other files except for .m2 . So I copied the .m2 directory into the new image.

### COPY app.jar and run

```sh
COPY target/demo-thin-docker-0.0.1-SNAPSHOT.jar /app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
```

Then as usual, copy the jar and run it.

### Offline Mode

To check there's no download on runtime, I used the - thin.offline=true to run docker with offline mode.

```sh
❯ docker run -p 8080:8080 demo-thin-docker - thin.debug=true - thin.offline=true
```

## The good parts with docker

As long as we don't change the dependencies, the library layer is reused. So the build finishes in no time.

That's all for today's fun. And I'm thinking what kind of usage fits to Thin Jar and Fat Jar.