- Creating Docker Images
This guide describes how to create a Docker image for your Helidon application, using a Java 8 base image or a custom Java 11 JRE built with
jlink.
What You Need
| About 10 minutes |
| Helidon Prerequisites |
You’ll also need Java 11 if you want to create custom JRE’s using jlink |
Java Packaging
The Helidon team recommends setting-up the class-path inside the META-INF/MANIFEST.MF file with the Class-Path entry pointing to dependency jar files in a co-located lib directory. See the Maven and Gradle examples for more details on how to package your Helidon application.
This approach is a good fit for Docker images:
the application code and dependencies can be separate image layers.
the image layer containing your dependencies is re-built only when dependencies are updated.
the deployment environment(s) pull the images layer containing your dependencies only when changed.
Why no fat jars?
Fat Jars are jar files that contain the application and its dependencies ; they are not optimal for Docker images as it results in a single image layer.
Creating a Java 8 Based Docker Image
This section describes the Dockerfile provided by the Helidon SE and MP quickstarts.
The Dockerfile is located at ./Dockerfile and contains the following:
# Multistage Docker build.
# 1st stage, build the app
FROM maven:3.5.4-jdk-9 as build
WORKDIR /helidon
# Create a first layer to cache the "Maven World" in the local repository.
# Incremental docker builds will always resume after that, unless you update
# the pom
ADD pom.xml .
RUN mvn package -DskipTests
# Do the Maven build!
# Incremental docker builds will resume here when you change sources
ADD src src
RUN mvn package -DskipTests
RUN echo "done!"
# 2nd stage, build the runtime image
FROM openjdk:8-jre-slim
WORKDIR /helidon
# Copy the binary built in the 1st stage
COPY --from=build /helidon/target/helidon-quickstart-se.jar ./
COPY --from=build /helidon/target/libs ./libs
CMD ["java", "-jar", "helidon-quickstart-se.jar"] - This is a multi-stage Docker build. See more info here
- The first stage that creates the build artifacts
- Create a layer, using just the
pom.xml, that contains the Maven cache. - When resuming here, Maven won’t re-download the world.
- The final stage that creates the image for our application.
- Using a lightweight image.
- The command to start the application.
mvn packagedocker build -t quickstart-se targetdocker run --rm -p 8080:8080 quickstart-se:latestcurl -X GET http://localhost:8080/greetCreating a Docker Image with a Custom JRE
This section describes how to build an image with a custom Java 11 JRE using jlink.
Replace Dockerfile with the following:
# Multistage Docker build.
# Stage 1: Build custom Java 11 JRE and put it in /var/tmp/myjre
FROM openjdk:11-slim AS myjre
RUN ["jlink", "--compress=2", "--strip-debug", "--no-header-files", \
"--add-modules", "java.base,java.logging,java.sql,java.desktop,java.management", \
"--output", "/var/tmp/myjre"]
# Work around for https://github.com/docker-library/openjdk/issues/217
RUN [ "apt", "update"]
RUN [ "apt-get", "install", "-y", "binutils"]
RUN ["strip", "-p", "--strip-unneeded", "/var/tmp/myjre/lib/server/libjvm.so"]
# End work-around
# Stage 2: Build application image using JRE from Stage 1
FROM debian:sid-slim
COPY --from=myjre /var/tmp/myjre /opt/jre
ENV PATH=$PATH:/opt/jre/bin
RUN mkdir /app
COPY libs /app/libs
COPY ${project.artifactId}.jar /app
CMD ["java", "-jar", "/app/${project.artifactId}.jar"]- This is a multi-stage Docker build. See more info here
- The first stage that creates our custom JRE.
- The modules listed in this example are for Helidon SE. See below for Helidon MP.
- This is a work-around for https://github.com/docker-library/openjdk/issues/217.
- The final stage that creates the image for our application.
- Use
debian:sid-slimto match the base image ofopenjdk:11-slim - Copy the JRE from the image of the first stage
myjre
mvn process-resourcesdocker build -t java11-quickstart-se targetdocker run --rm -p 8080:8080 java11-quickstart-se:latestcurl -X GET http://localhost:8080/greetdocker images java11-quickstart-se:latestREPOSITORY TAG IMAGE ID CREATED SIZE
java11-quickstart-se latest f07a7b8bda78 About a minute ago 136MB~140MB is less than the pre-built OpenJDK slim JRE images. Results might differ a bit depending on your platform.
What about Helidon MP?
For Helidon MP you need to add a couple more modules to the jlink command:
RUN ["jlink", "--compress=2", "--strip-debug", "--no-header-files", \
"--add-modules", \
"java.base,java.logging,java.sql,java.desktop,java.management,java.naming,jdk.unsupported", \
"--output", "/var/tmp/myjre"]