Mohammed Aboullaite, xHub
Nowadays, containers are more than a cool new tool to play with - they've revolutionized the way we develop, architect and ship software and have become part of our day-to-day operations. On the other hand, Java has been around for more than 2 decades, dominating the entreprise world. Both advocate the "RUN anywhere" principal, but, is it that easy? No! Your perfect working local container will most probably fail on production because of MEMORY &/or CPU issues, since jvm apps assume they OWN the server they are running on.
This session will look at the gotchas of running JVM apps in containers & how to avoid costly pitfalls. We will cover:
_ what updates Java 10 brought to the table to improve container awareness and the issues related to prior versions, including how to address each one of them to avoid the mess.
- tips and tricks to obtain smaller images & best practices while writing your DockerFiles
- some plugins to helps non-containers experts integrate docker in their development process; and
- the concept of "Distroless" Docker Images and how to benefit from it.
4. Agenda
● Java in containers … a good idea ?
● Creating effective Java Docker Images: smaller, faster, secure.
● Tools and libraries: build, versioning, testing
● Going to production … what we should know !?
● Java & Docker Container features
11. Did someone say alpine ?!
Lightweight Linux distribution based on musl libc and busybox
Project Portola: https://openjdk.java.net/projects/portola/
14. Distroless Container Image
“Distroless" images contain only your application and its runtime
dependencies. They do not contain package managers, shells or any
other programs you would expect to find in a standard Linux
distribution.”
● Built using Google’s bazel tool
● Provide stripped down base image
● Support for: Java, Golang, Dotnet, Node, Python, C
https://github.com/GoogleContainerTools/distroless
15. Why should I care ?!
● Effective tracking: Improves the signal to noise of scanners (e.g.
CVE)
● Time and cost: Faster updates, less network costs
● Security: Less components that can be exploited and smaller attack
surface
Tips and tricks from Docker captains
16. Fast startup
Java
• Java 11
• Class-Data Sharing: since java 5
• Ahead-Of-Time compilation: since java 9
• Native image build: Graal VM
25. Security
● Know what in your container
● Vulnerability scanning (Docker EE, Microscanner, Clair, ...)
● Docker Content Trust
● Least privilege
○ Change USER
○ Read-only filesystems
○ Limit ressources
● Minimal container OS (Minimal attack surface)
● Monitoring & Auditing
Tips and tricks from the captains session
26. How about
(Integration) testing!
● Real world isolated testing
● Can be run during development
● Reproducible
● As real as possible (databases,
brokers, ...)
● Cross platform
● Spot issues before they appear in
prod
● Easy to run & maintain!!!
27. TestContainers
● Java library
● Supports of JVM testing framework
(JUnit, Spock, ...)
● Provides lightweight, throwaway
instances of common databases
● Port randomisation
● Containers Cleanup on JVM
shutdown
GenericContainer redis =
new GenericContainer( "redis:3.0.6")
.withExposedPorts( 6379);
28. Let’s go to (pre-)production!
● Petclinic: Spring App
● Modernizing legacy app with containers
● Optimizing resources
● Easy scaling
● Cloud ready
● Orchestration
31. A brief history of containers & ...
Container Runtime and Image Format Standards - Jeff Borek & Stephen Walli - KubeCon 2017
32. … & Java!
zeroturnaround - A Short History of Nearly Everything Java
https://zeroturnaround.com/rebellabs/a-short-history-of-nearly-everything-java/
33. JVM ergonomics
The JVM has plenty of ergonomics which are based on the underlying
system
● Memory
● # CPUs
● Exact CPU model
● Garbage collector
● JIT Optimizations
⇒ -XX:+PrintFlagsFinal -XX:+PrintGCDetails
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/ergonomics.html
37. Fabric8 got it right
https://github.com/fabric8io-images/run-java-sh
38. java 9, 8u131
● -XX:ParallelGCThreads and -XX:CICompilerCount are set based on
Containers CPU limits (can be overridden)
○ calculated from --cpuset-cpus
● Memory Configuration
○ -XX:+UnlockExperimentalVMOptions
○ -XX:+UseCGroupMemoryLimitForHeap
○ set -XX:MaxRAMFraction to 2 (default is 4)
39. Java 10+ & 8u191 +
More container awareness
● Improve heap memory allocations [JDK-8196595]:
○ -XX:InitialRAMPercentage, -XX:MaxRAMPercentage and
-XX:MinRAMPercentage
○ -XX:InitialRAMFraction, -XX:MaxRAMFraction, and
-XX:MinRAMFraction are Deprecated
● The total number of CPUs available to the Java process is calculated from
--cpus, --cpu-shares, --cpu-quota [JDK-8146115]
○ Use -XX:-UseContainerSupport to return to the old behavior
○ # processors that the JVM will use internally -XX:ActiveProcessorCount
● Attach in linux became be relative to /proc/pid/root and namespace aware
(jcmd, jstack, etc)
40. Java 11
More container awareness
● Removes -XX:+UnlockExperimentalVMOptions,
-XX:+UseCGroupMemoryLimitForHeap [JDK-8194086]
● jcmd -l and jps commands do not list JVMs in Docker containers
[JDK-8193710]
● Container Metrics (-XshowSettings:system) [JDK-8204107]
● Update CPU count algorithm when both cpu shares and quotas are
used [JDK-8197867]
○ -XX:+PreferContainerQuotaForCPUCount