It's easy to make mistakes when Dockerizing your Java applications. In this webinar, Alexei Ledenev (Cheif Researcher at Codefresh) shared his experience on how to craft the perfect Java-Docker build flow. He explained best practices and common pitfalls, then demonstrated how to create a build pipeline that consistently produces small, efficient, and secure Docker images. View the webinar recording and summary here- https://codefresh.io/blog/webinar-creating-efficient-docker-build-pipeline-java-apps/
2. About me…
•Chief of Research @codefresh.io
•github.com/alexei-led/pumba
•#docker, #golang, #aws
•medium.com/@alexeiled
•@alexeiled
3. The “Naive” Approach
Follow familiar VM build and install flow
# start from ubuntu
FROM ubuntu:14.04
# add required packages and java repository
RUN apt-get update && apt-get install -y python-software-properties software-properties-
common
RUN add-apt-repository ppa:webupd8team/java
# install Oracle JDK 8 with auto-accept license agreement
RUN echo "oracle-java8-installer shared/accepted-oracle-license-v1-1 boolean true" |
debconf-set-selections
RUN apt-get update && apt-get install -y oracle-java8-installer maven
# add ALL project files
ADD . /usr/local/app
# build Java application with Maven (fetch packages, compile, test and deploy)
RUN cd /usr/local/app && mvn install
# define default command to run the application
CMD ["/usr/bin/java", "-jar", "-Dspring.profiles.active=test", "/usr/local/app/target/
spring-boot-rest-example-0.3.0.war"]
Docker Image Size = 1.3 GB
Docker Built Time = 27 min
4. “Standard” Approach
FROM java:8
# Install maven
RUN apt-get update
RUN apt-get install -y maven
WORKDIR /code
# Prepare by downloading dependencies
ADD pom.xml /code/pom.xml
RUN ["mvn", "dependency:resolve"]
RUN ["mvn", "verify"]
# Adding source, compile and package into a fat jar
ADD src /code/src
RUN ["mvn", "package"]
EXPOSE 4567
CMD ["/usr/bin/java", "-jar", "-Dspring.profiles.active=test", "target/spring-boot-rest-
example-0.3.0.war"]
Docker Image Size = 1.2 GB
Docker Built Time = 15 min
Take Library OpenJDK image, add pom.xml first…
5. Stay away from these abstractions
Containers are not VM
and
they are not like “lightweight” VM
6. –Joe Fernandes, senior director, OpenShift Product Management, Red Hat
“A Linux container is nothing more than a
process that runs on Linux. It shares a host
kernel with other containerized processes.”
7. What is the bare minimum
required to run Java App?
1. Base Image with C Runtime and Posix shell (Alpine)
2. Java Runtime Environment (OpenJDK JRE)
3. Application byte-code and resources (app.jar)
4. 3rd Party Libraries (lib/*.jar)
5. Optionally HTTP server (Tomcat/Jetty/Netty/…)
8. Docker Image Size
• time to build
• network latency
• storage
• service availability and elasticity
• security
• development agility
10. Java Docker Builder
1. Base Image with C Runtime and Posix shell (Alpine)
2. Java Development Kit (OpenJDK)
3. Javac or other JVM compiler (Scala, Kotlin, …)
4. Build Management Tool (Maven, SBT, Gradle, …)
5. Linters, code scanners, test frameworks, test tools, …
11. Maven Builder Dockerfile
FROM openjdk:8-jdk-alpine
RUN apk add --no-cache curl tar bash
ARG MAVEN_VERSION=3.3.9
ARG USER_HOME_DIR="/root"
RUN mkdir -p /usr/share/maven &&
curl -fsSL http://apache.osuosl.org/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-
$MAVEN_VERSION-bin.tar.gz | tar -xzC /usr/share/maven --strip-components=1 &&
ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"
# speed up Maven JVM a bit
ENV MAVEN_OPTS="-XX:+TieredCompilation -XX:TieredStopAtLevel=1"
ENTRYPOINT ["/usr/bin/mvn"]
# make source folder
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# install maven dependency packages (keep in image)
COPY pom.xml /usr/src/app
RUN mvn -T 1C install && rm -rf target
# copy other source files (keep in image)
COPY src /usr/src/app/src