WebSphere Application Server & Liberty

 View Only

Liberty Container Performance Optimizations

By Joe McClure posted Mon September 13, 2021 10:23 AM


In a previous blog post, Lessons from the field #8: Liberty in containers part 1: Java performance , Brent Daniel discussed Java performance in Liberty containers. In this blog post, I will go into more detail on optimizing Liberty performance in containers for startup time and image size based on options provided in the Dockerfile.

Before I begin, here is where you can currently find our container images based on Ubuntu and Universal Base Image (UBI).

The examples below use the Auth Service of the Acme Air Microservices Benchmark. If you want to play along at home, you can find that here: https://github.com/blueperf/acmeair-authservice-java. I will be modifying the Dockerfile found there, below.

Liberty Startup Time

As Brent discussed, one way to improve the startup time of Liberty containers is to make sure the Shared Class Cache (SCC) is pre-populated with your application classes when the image is built. This is achieved by running the "configure.sh" script as the last step of building the end image.

As you can see below, adding a SCC to the image can cut startup time of the container in half. These measurements were done on my MacBook, which is not a controlled performance measurement environment, but demonstrates the magnitude of improvement provided by the SCC.


To do this, simply add the following line to the end of your Dockerfile:

RUN configure.sh

However, there are two performance tradeoffs with doing this. One is that the image size will be a bit larger due to adding the SCC (max of 80mb). The other is that building the image will take longer. This is because to generate the SCC, Liberty must be started and stopped twice. This added 35 seconds to the build time in my Macbook environment. If you value a faster build time over a faster startup time, you can add the option below before configure.sh, which will disable the generation of the SCC.

RUN configure.sh

The configure.sh script does more than generate an SCC, so you should always include it at the end of your Dockerfile whether you enable OPENJ9_SCC or not. See https://github.com/OpenLiberty/ci.docker#enterprise-functionality.

Note: I obtained these numbers by starting the containers like this:


I used docker inspect to get the time the Liberty container began starting. Then I used curl to loop on http://localhost:9080/auth and waited for an “OK” response to get the time that all the endpoints were ready for requests. The time difference is what we call Time to First Response.


Liberty Image Size

Liberty images come in two different flavors

  • kernel-slim (open-liberty) or kernel (websphere-liberty)
  • full


The full images are packaged with many features. This is super convenient, but large, and it is doubtful that you will need most of those features for your application. The kernel images are packaged with no features. You can then add only the features you need for your application.

Here is a comparison of the final image size (all of the layers) of the Acme Air Auth Service with open-liberty:full vs open-liberty:kernel-slim with the microProfile-4.1 feature in the server.xml.

The steps to build an image based on the “kernel/kernel-slim” image are a bit different for open-liberty and websphere-liberty,

Example Open-Liberty Dockerfile – In open-liberty, the features.sh script uses the featureUtility to download the features specified in the server.xml. To better take advantage of build caching, run this script directly after copying over the server.xml in the Dockerfile.

FROM open-liberty:kernel-slim
# Config
COPY --chown=1001:0 src/main/liberty/config/server.xml /config/server.xml
RUN features.sh
COPY --chown=1001:0 src/main/liberty/config/server.env /config/server.env
<rest of Dockerfile>
RUN configure.sh


Example WebSphere-Liberty Dockerfile – In the websphere-liberty:kernel image, the features are downloaded with the installUtility inside of the configure.sh script. This should be done at the end of the Dockerfile (like we talked about above in the startup section).

FROM websphere-liberty:kernel
# Config
COPY --chown=1001:0 src/main/liberty/config/server.xml /config/server.xml
COPY --chown=1001:0 src/main/liberty/config/server.env /config/server.env
<rest of Dockerfile>
RUN configure.sh

One tradeoff of using a kernel image is increased build time because the features must be downloaded. This time was improved in Open Liberty in, but still adds 60 seconds on my MacBook. If you are developing and changing things often or running in a build pipeline that builds and deploys only one time, it may be more convenient to use the full images.

I hope this blog post helped you understand how to optimize Liberty for performance in containers for startup time and image size, and to understand the tradeoffs that come along with those optimizations.