Runtime & JVM

Creating a container for a Vert.x app packaged as an executable uber-jar

What you will create

You will create a container for a Vert.x app packaged as an executable uber-jar.

The how-to consists in a couple of files:

  1. the docker-maven/Dockerfile, for Maven users, or

  2. the docker-gradle/Dockerfile, for Gradle users.

What you need

  • A text editor or IDE

  • Docker

Using Maven

Generate the project

First, generate the project from https://start.vertx.io:

  1. Select the Maven build type

  2. Set the artifactId to container-uber-jar

  3. Select the JDK 11 JDK version

  4. Click on generate and extract the content somewhere on your disk

Generating a Maven Project
Figure 1. Generating a Maven Project

Alternatively, open a terminal and run:

curl -G https://start.vertx.io/starter.zip -d "artifactId=container-uber-jar" -d "jdkVersion=11" -d "buildTool=maven" --output container-uber-jar.zip
unzip container-uber-jar.zip

Or, with HTTPie:

http https://start.vertx.io/starter.zip artifactId==container-uber-jar jdkVersion==11 buildTool==maven --output container-uber-jar.zip
unzip container-uber-jar.zip

Configuring the Docker build

At the root of the project, create a docker-maven/Dockerfile build file:

Docker build file for a Maven project
# 1st Docker build stage: build the project with Maven
FROM maven:3.6.3-openjdk-11 as builder
WORKDIR /project
COPY . /project/
RUN mvn package -DskipTests -B

# 2nd Docker build stage: copy builder output and configure entry point
FROM adoptopenjdk:11-jre-hotspot
ENV APP_DIR /application
ENV APP_FILE container-uber-jar.jar

EXPOSE 8888

WORKDIR $APP_DIR
COPY --from=builder /project/target/*-fat.jar $APP_DIR/$APP_FILE

ENTRYPOINT ["sh", "-c"]
CMD ["exec java -jar $APP_FILE"]

The Docker build has two stages:

  1. Building the Maven project inside a maven:3.6.3-openjdk-11 container

  2. Copying the output of the build in a adoptopenjdk:11-jre-hotspot container and configuring the entry point

The benefits of this approach are:

  • reproducible build: no matter who in the team runs the Docker build, it will always use the same Maven version and JDK version (both at build-time and run-time)

  • small container image size: the final container will be based on a slim JDK image and will only add the uber-jar file

To build the container, open a terminal at the root of the project and run:

docker build -t com.example/container-uber-jar -f docker-maven/Dockerfile .

Using Gradle

Generate the project

First, generate the project from https://start.vertx.io:

  1. Select the Gradle build type

  2. Set the artifactId to container-uber-jar

  3. Select the JDK 11 JDK version

  4. Click on generate and extract the content somewhere on your disk

Generating a Gradle Project
Figure 2. Generating a Gradle Project

Alternatively, open a terminal and run:

curl -G https://start.vertx.io/starter.zip -d "artifactId=container-uber-jar" -d "jdkVersion=11" -d "buildTool=gradle" --output container-uber-jar.zip
unzip container-uber-jar.zip

Or, with HTTPie:

http https://start.vertx.io/starter.zip artifactId==container-uber-jar jdkVersion==11 buildTool==gradle --output container-uber-jar.zip
unzip container-uber-jar.zip

Configuring the Docker build

At the root of the project, create a docker-gradle/Dockerfile build file:

Docker build file for a Gradle project
# 1st Docker build stage: build the project with Gradle
FROM gradle:6.8.3-jdk11 as builder
WORKDIR /project
COPY . /project/
RUN gradle assemble --no-daemon

# 2nd Docker build stage: copy builder output and configure entry point
FROM adoptopenjdk:11-jre-hotspot
ENV APP_DIR /application
ENV APP_FILE container-uber-jar.jar

EXPOSE 8888

WORKDIR $APP_DIR
COPY --from=builder /project/build/libs/*-fat.jar $APP_DIR/$APP_FILE

ENTRYPOINT ["sh", "-c"]
CMD ["exec java -jar $APP_FILE"]

The Docker build has two stages:

  1. Building the Gradle project inside a gradle:6.8.3-jdk11 container

  2. Copying the output of the build in a adoptopenjdk:11-jre-hotspot container and configuring the entry point

The benefits of this approach are:

  • reproducible build: no matter who in the team runs the Docker build, it will always use the same Gradle version and JDK version (both at build-time and run-time)

  • small container image size: the final container will be based on a slim JDK image and will only add the uber-jar file

To build the container, open a terminal at the root of the project and run:

docker build -t com.example/container-uber-jar -f docker-gradle/Dockerfile .

Running the application

Now that you have built the container image, it is time to try it out!

Open a terminal and run:

docker run -p 8888:8888 com.example/container-uber-jar

You should see messages like these on the console output:

HTTP server started on port 8888
Mar 16, 2021 2:45:57 PM io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer
INFO: Succeeded in deploying verticle

Then browse to http://localhost:8888 and get your greeting from the Vert.x app running in the container!

Summary

This document covered:

  1. configuring a Docker build for Maven users,

  2. configuring a Docker build for Gradle users.