DEV Community

Andrei
Andrei

Posted on • Originally published at Medium on

6 3

Dockerizing Java 10 Spring Boot app

In my previous article I’ve been talking about using Java 10 to build and run your Spring Boot app. Now it is time to talk how to put it in Docker container. Better support of containerization was one of the main features of Java 10 release. So, let’s go!

That is fairly simple process, so just take a look on following code snippet:

FROM debian:9-slim AS builder
RUN set -ex && \
apt-get update && apt-get install -y wget unzip && \
wget https://download.java.net/java/GA/jdk11/9/GPL/openjdk-11.0.2_linux-x64_bin.tar.gz -nv -O jdk.tar.gz -nv && \
mkdir -p /opt/jdk && \
tar zxvf jdk.tar.gz -C /opt/jdk --strip-components=1 && \
rm jdk.tar.gz && \
rm /opt/jdk/lib/src.zip
RUN /opt/jdk/bin/jlink \
--module-path /opt/jdk/jmods \
--verbose \
--add-modules java.base,java.logging,java.xml,jdk.unsupported,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument \
--output /opt/jdk-minimal \
--compress 2 \
--no-header-files
# Second stage, add only our custom jdk9 distro and our app
FROM debian:9-slim
COPY --from=builder /opt/jdk-minimal /opt/jdk-minimal
ENV JAVA_HOME=/opt/jdk-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
ENV APP_TIMEZONE=UTC
EXPOSE 8080
ENTRYPOINT ["/launch.sh"]
COPY launch.sh /
RUN chmod +x /launch.sh
COPY build/libs/you-app.jar /app.jar
view raw Dockerfile hosted with ❤ by GitHub

Here, as you can see, I use multi-stage Docker build file. Quick note: multi-stage builds are supported with Docker 17.05 or higher but result image is backward compatible(at least from my experience). On the first stage it downloads JDK from Oracle’s, but it can make sense to store your own copy somewhere closer to your build server since it isn’t that small — a little bit less then 200mb. So, it is downloaded, unziped and ready to be used. But not so quick.

As you probably remember, Java 9 gave us module system and JDK itself is also modularized. That means we don’t have to bring whole JDK to production but we could build our own striped version specifically for our app’s needs. There is jlink tool provided for that. Just take a look how it is used in the build process. The modules listed there should be enough to run a typical Spring Boot application. In my production case I had to put java.scripting, jdk.scripting.nashorn to the list as well.

On the second stage it copies results from previous one, defines some environment variables, exposes port, copy launch.sh and app’s artifact. Not a rocket science at all.

And here is launch.sh script I’ve just mentioned:

#!/bin/bash
check_var(){
if [ -z "$1" ]; then
>&2 echo "error: missing environmental variable $2. exit"
exit 1
fi
}
check_var "${JAVA_XMS}" "JAVA_XMS"
check_var "${JAVA_XMX}" "JAVA_XMX"
check_var "${APP_TIMEZONE}" "APP_TIMEZONE"
XMS=${JAVA_XMS:-none}
XMX=${JAVA_XMX:-none}
TIMEZONE=${APP_TIMEZONE:-none}
JAVA_OPTS="-Xmx${XMX} -Xms${XMS} -Duser.timezone=${TIMEZONE} -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE} ${OPTIONS}"
java ${JAVA_OPTS} -jar /app.jar
view raw launch.sh hosted with ❤ by GitHub

That is just a small helper to ensure that there are all important things provided, etc. But, sure, it is optional.

And that should be enough to put your app to the production. Please, put some comments down if you have some thoughts how to make it better!

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay