Red Hat provides Red Hat build of OpenJDK to run Java applications in Red Hat OpenShift 4. While OpenShift manages container builds on-cluster, developers can also use the standalone Source-to-Image (S2I) CLI to build and test OpenJDK container images locally before deploying them.
The procedures in this guide apply to Red Hat OpenShift 4 and current releases of the Red Hat build of OpenJDK.
S2I standalone toolkit
Source-to-Image (S2I) is a toolkit and workflow for building reproducible container images from source code. S2I produces ready-to-run images by injecting source code into a container image and letting the container prepare that source code for execution. By creating self-assembling builder images, you can version and control your build environments exactly like you use container images to version your runtime environments.
You can create a builder image containing OpenJDK and Tomcat that expects a Web Application Archive (WAR) file while taking advantage of the container-awareness settings provided by the Red Hat build of OpenJDK.
The S2I standalone toolkit helps you build local OpenJDK images from scratch directly from the builder image without requiring additional build tools such as Shipwright or Jenkins.
For the S2I toolkit, see openshift/source-to-image for details on Source-to-Image options, including:
| Option | Purpose |
|---|---|
--as-dockerfile | Output a Dockerfile to this path instead of building a new image |
--assemble-user | Specify the user to run assemble with |
--assemble-runtime-user | Specify the user to run assemble-runtime with |
--environment-file | Specify an environment file |
S2I standalone toolkit examples
The following examples demonstrate how to use the S2I standalone toolkit in different scenarios.
S2I toolkit example 1
To inspect the assembly details during a local build, run S2I with the --loglevel flag:
#####
##### Clone
#####
$ git clone https://github.com/alexbarbosa1989/hotrodspringboot.git
#####
##### Build
#####
$ sudo s2i --loglevel 5 build hotrodspringboot/ registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128 openjdk-hotrod:example
I0917 17:04:30.472443 3630734 build.go:52] Running S2I version "v1.5.1"
I0917 17:04:30.472640 3630734 util.go:70] Getting docker credentials for registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128
I0917 17:04:31.299838 3630734 docker.go:520] error inspecting image registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128: Error response from daemon: No such image: registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128
I0917 17:04:31.299897 3630734 docker.go:507] Image "registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128" not available locally, pulling ... <--- not local
I0917 17:04:31.769980 3630734 build.go:170]
Builder Name: Java Applications
Builder Image: registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128
Source: hotrodspringboot/
Output Image Tag: openjdk-hotrod:example
Environment:
Labels:
Incremental Build: disabled
Remove Old Build: disabled
Builder Pull Policy: if-not-present
Previous Image Pull Policy: if-not-present
Quiet: disabled
Layered Build: disabled
Docker Endpoint: unix:///var/run/docker.sock
Docker Pull Config: /root/.docker/config.json
Docker Pull User:
I0917 17:04:31.771431 3630734 docker.go:511] Using locally available image "registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128"
I0917 17:04:31.776867 3630734 docker.go:511] Using locally available image "registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128"
I0917 17:04:31.776883 3630734 docker.go:751] Image sha256:abf8175bbfa5d74cfafba2eaa358914aac1fccaee4b0013e64eb6d1a289a4ec5 contains io.openshift.s2i.scripts-url set to "image:///usr/local/s2i"
I0917 17:04:31.776908 3630734 scm.go:20] DownloadForSource hotrodspringboot/
I0917 17:04:31.777198 3630734 sti.go:206] Preparing to build openjdk-hotrod:example
I0917 17:04:31.777595 3630734 clone.go:37] Downloading "hotrodspringboot/" ...
I0917 17:04:31.777608 3630734 clone.go:41] Cloning sources into "/tmp/s2i4104424273/upload/src"
I0917 17:04:31.823469 3630734 clone.go:57] Checked out "HEAD"
I0917 17:04:31.851049 3630734 clone.go:63] Updated submodules for "HEAD"
...
...
#####
##### Run
#####
$ #sudo s2i --loglevel 5 build hotrodspringboot/ registry.access.redhat.com/ubi8/openjdk-17:1.23-5.1789111128 openjdk-hotrod:example
fdemeloj@fdemeloj-thinkpadp16vgen1:~/Downloads/Redhat/openjdk$ sudo docker run -p 8081:8080 openjdk-hotrod:example
Starting the Java application using /opt/jboss/container/java/run/run-java.sh ...
INFO exec -a "java" java -XX:MaxRAMPercentage=80.0 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -cp "." -jar /deployments/hotrodspringboot-0.0.1-SNAPSHOT.jar
INFO running in /deployments
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.0)
2026-09-17 21:07:08.311 INFO 1 --- [ main] c.r.h.h.HotrodspringbootApplication : Starting HotrodspringbootApplication v0.0.1-SNAPSHOT using Java 17.0.20.1 on 77cbb90c6f5a with PID 1 (/deployments/hotrodspringboot-0.0.1-SNAPSHOT.jar started by jboss in /deployments)
2026-09-17 21:07:08.312 INFO 1 --- [ main] c.r.h.h.HotrodspringbootApplication : No active profile set, falling back to 1 default profile: "default"
2026-09-17 21:07:08.850 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2026-09-17 21:07:08.859 INFO 1 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2026-09-17 21:07:08.859 INFO 1 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.63]
2026-09-17 21:07:08.903 INFO 1 --- [ main] o.a.c.c.C.[.[localhost].[/redhat] : Initializing Spring embedded WebApplicationContext
2026-09-17 21:07:08.903 INFO 1 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 563 ms
2026-09-17 21:07:09.078 INFO 1 --- [ main] org.infinispan.HOTROD : ISPN004108: Native IOUring transport not available, using NIO instead: io.netty.incubator.channel.uring.IOUring
2026-09-17 21:07:09.160 INFO 1 --- [-async-pool-1-1] org.infinispan.SECURITY : ISPN000947: Using Java SSL Provider
...
...
2026-09-17 21:07:10.581 INFO 1 --- [ main] org.infinispan.HOTROD : ISPN004021: Infinispan version: Infinispan 'Flying Saucer' 14.0.30.Final-redhat-00001
2026-09-17 21:07:10.837 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '/redhat'
2026-09-17 21:07:10.845 INFO 1 --- [ main] c.r.h.h.HotrodspringbootApplication : Started HotrodspringbootApplication in 2.762 seconds (JVM running for 2.979)Here is the same example using a remote HTTPS repository rather than a local repository:
$ s2i --loglevel 5 build https://github.com/alexbarbosa1989/SessionReplication
registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549 openjdk-session:exampleS2I toolkit example 2
To customize JVM garbage collection and memory settings for a local build, define MAVEN_OPTS in an environment file. First, configure the environment file to pass arguments that replace default settings like ParallelGC with G1GC and adjust MaxRAMPercentage:
$ cat SessionReplication/.s2i/environment
MAVEN_OPTS=-XX:MaxRAMPercentage=80.0 -XX:+UseG1GC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=47.0 <--------Next, pass the environment file to the build using --environment-file:
$ s2i --loglevel 5 build SessionReplication/ --environment-file=/path/SessionReplication/.s2i/environment registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549 openjdk-session:example
I1202 15:18:56.344820 2010307 build.go:52] Running S2I version "unknown"
I1202 15:18:56.344951 2010307 util.go:70] Getting docker credentials for registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549
I1202 15:18:57.647464 2010307 docker.go:491] Using locally available image "registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549"
I1202 15:18:57.648659 2010307 build.go:170]
Builder Name: Java Applications
Builder Image: registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549
Source: SessionReplication/
Output Image Tag: openjdk-session:example
Environment: MAVEN_OPTS=-XX:MaxRAMPercentage=80.0 -XX:+UseG1GC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=47.3 <--------
Environment File: /path/SessionReplication/.s2i/environment
...
...
...
02 15:18:58.193346 2010307 tar.go:336] Adding to tar: /tmp/s2i680185875/upload/src/src/main/webapp/WEB-INF as src/src/main/webapp/WEB-INF
I1202 15:18:58.193411 2010307 tar.go:336] Adding to tar: /tmp/s2i680185875/upload/src/src/main/webapp/WEB-INF/jboss-web.xml as src/src/main/webapp/WEB-INF/jboss-web.xml
I1202 15:18:58.193476 2010307 tar.go:336] Adding to tar: /tmp/s2i680185875/upload/src/src/main/webapp/WEB-INF/web.xml as src/src/main/webapp/WEB-INF/web.xml
I1202 15:18:58.211148 2010307 sti.go:717] INFO Performing Maven build in /tmp/src
I1202 15:18:58.211183 2010307 sti.go:717] INFO Using MAVEN_OPTS -XX:MaxRAMPercentage=80.0 -XX:+UseG1GC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=47.3 <----------------------
...
...
I1202 15:26:15.270509 2011902 docker.go:1104] Committing container with dockerOpts: {Reference:openjdk-session:example Comment: Author: Changes:[] Pause:false Config:0xc0000f8500}, config: {Hostname: Domainname: User:185 AttachStdin:false AttachStdout:false AttachStderr:false ExposedPorts:map[] Tty:false OpenStdin:false StdinOnce:false Env:[MAVEN_OPTS=-XX:MaxRAMPercentage=80.0 -XX:+UseG1GC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=47.3]
...
$ sudo docker image ls IMAGE ID DISK USAGE CONTENT SIZE EXTRA
openjdk-session:example ffca3b820afe 424MB 0B S2I toolkit example 3
To pass custom repository configurations during local builds, define MAVEN_OPTS alongside MAVEN_SETTINGS_XML:
$ cat SessionReplication/.s2i/environment
MAVEN_OPTS=-XX:MaxRAMPercentage=80.0 -XX:+UseG1GC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=47.0 <--------
MAVEN_SETTINGS_XML=/path/custom/custom_settings.xmlNext, pass the environment file to the build using --environment-file:
$ s2i --loglevel 5 build SessionReplication/ --environment-file=/path/SessionReplication/.s2i/environment registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549 openjdk-session:example
I1202 15:18:56.344820 2010307 build.go:52] Running S2I version "unknown"
I1202 15:18:56.344951 2010307 util.go:70] Getting docker credentials for registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549
I1202 15:18:57.647464 2010307 docker.go:491] Using locally available image "registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549"
I1202 15:18:57.648659 2010307 build.go:170]
Builder Name: Java Applications
Builder Image: registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549
Source: SessionReplication/
Output Image Tag: openjdk-session:example
Environment: MAVEN_OPTS=-XX:MaxRAMPercentage=80.0 -XX:+UseG1GC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=47.3,MAVEN_SETTINGS_XML=/path/custom_settings.xml <--------
Environment File: /path/SessionReplication/.s2i/environmentS2I toolkit example 4
To save build configurations for repeatable execution, define your build parameters in an environment file:
BASEIMG=registry.access.redhat.com/ubi9/openjdk-17:1.18 (b)
APPSRC=https://github.com/jboss-container-images/openjdk-test-applications (a)
CONTEXTDIR=spring-boot-sample-simple/target # trigger binary build
rev=master
OUTIMG=s2i-out (c)
s2i build --pull-policy never --context-dir=$CONTEXTDIR -r=${rev} \ (d)
--loglevel 1 \
--as-dockerfile tmp/Dockerfile \
--image-scripts-url image:///usr/local/s2i \ $APPSRC \
$BASEIMG \
$OUTIMGWhen using the S2I standalone toolkit, issues such as permission errors can occur.
BuildConfig examples
The following examples provide context and comparison with Red Hat OpenShift 4 builds. These examples come from the article 4 ways to deploy Quarkus applications in OpenShift Container Platform 4 and cover Source-to-Image and binary builds:
BuildConfig example 1: Source build
This example uses the source code and the ubi8/openjdk image to create the build and runtime container:
oc new-app --context-dir=getting-started --name=quarkus-quickstart \
'registry.access.redhat.com/ubi8/openjdk-11~https://github.com/quarkusio/quarkus-quickstarts.git#2.12.1.Final'BuildConfig example 2: Binary build
This example uses a binary artifact and the ubi8/openjdk image to build the container image:
$ oc new-app binaryopenjdk-scenario2b/openjdk-11:1.17-1.1693366250~/tmp/nocontent --name=example-jdk11-rhel7
...
$ oc start-build example-jdk11-rhel7 --from-file=./application-runner.jar
Uploading file "application-runner.jar" as binary input for the build ...
Uploading finished
build.build.openshift.io/example-jdk11-rhel7-2 startedFor additional build configurations, refer to the Red Hat build of OpenJDK documentation.
Output review and comments
Review the following build output log generated by running the S2I build command:
$ git clone https://github.com/alexbarbosa1989/SessionReplication
$ s2i --loglevel 5 build SessionReplication/ registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549 openjdk-session:example
I1203 20:02:47.126298 2137054 build.go:52] Running S2I version "unknown"
I1203 20:02:47.126451 2137054 util.go:70] Getting docker credentials for registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549
I1203 20:02:49.451343 2137054 docker.go:491] Using locally available image "registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549"
I1203 20:02:49.453150 2137054 build.go:170]
Builder Name: Java Applications
Builder Image: registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549
Source: SessionReplication/
Output Image Tag: openjdk-session:example
Environment:
Labels:
Incremental Build: disabled
Remove Old Build: disabled
Builder Pull Policy: if-not-present
Previous Image Pull Policy: if-not-present
Quiet: disabled
Layered Build: disabled
Docker Endpoint: unix:///var/run/docker.sock
...
I1203 20:02:49.454508 2137054 docker.go:491] Using locally available image "registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549"
I1203 20:02:49.459541 2137054 docker.go:491] Using locally available image "registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549"
I1203 20:02:49.459553 2137054 docker.go:731] Image sha256:2bb4972fa48644f10ec81e0b2c192381c018ad0006769ffec6fab463ba4a2705 contains io.openshift.s2i.scripts-url set to "image:///usr/local/s2i"
I1203 20:02:49.459564 2137054 scm.go:20] DownloadForSource SessionReplication/
I1203 20:02:49.459678 2137054 sti.go:206] Preparing to build openjdk-session:example
I1203 20:02:49.459766 2137054 clone.go:37] Downloading "SessionReplication/" ...
I1203 20:02:49.459774 2137054 clone.go:41] Cloning sources into "/tmp/s2i3625065130/upload/src"
I1203 20:02:49.467909 2137054 clone.go:57] Checked out "HEAD"
I1203 20:02:49.487588 2137054 clone.go:63] Updated submodules for "HEAD"
I1203 20:02:49.497452 2137054 install.go:269] Using "assemble" installed from "image:///usr/local/s2i/assemble"
I1203 20:02:49.497474 2137054 install.go:269] Using "run" installed from "image:///usr/local/s2i/run"
I1203 20:02:49.497490 2137054 install.go:269] Using "save-artifacts" installed from "image:///usr/local/s2i/save-artifacts"
I1203 20:02:49.497504 2137054 ignore.go:66] .s2iignore file does not exist
I1203 20:02:49.497512 2137054 sti.go:215] Clean build will be performed
I1203 20:02:49.497519 2137054 sti.go:218] Performing source build from SessionReplication/
I1203 20:02:49.497525 2137054 sti.go:227] Running "assemble" in "openjdk-session:example" as "185" user
I1203 20:02:49.497531 2137054 sti.go:587] Using image name registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549
I1203 20:02:49.498696 2137054 docker.go:491] Using locally available image "registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549"
I1203 20:02:49.498715 2137054 sti.go:467] No user environment provided (no environment file found in application sources)
I1203 20:02:49.498737 2137054 sti.go:705] starting the source uploading ...
I1203 20:02:49.498749 2137054 tar.go:238] Adding "/tmp/s2i3625065130/upload" to tar ...
I1203 20:02:49.499825 2137054 tar.go:336] Adding to tar: /tmp/s2i3625065130/upload/scripts as scripts
I1203 20:02:49.500993 2137054 docker.go:731] Image sha256:2bb4972fa48644f10ec81e0b2c192381c018ad0006769ffec6fab463ba4a2705 contains io.openshift.s2i.scripts-url set to "image:///usr/local/s2i"
I1203 20:02:49.501002 2137054 docker.go:805] Base directory for S2I scripts is '/usr/local/s2i'. Untarring destination is '/tmp'.
I1203 20:02:49.501009 2137054 docker.go:962] Setting "/bin/sh -c tar -C /tmp -xf - && /usr/local/s2i/assemble" command for container ...
I1203 20:02:49.501068 2137054 docker.go:971] Creating container with options {Name:"s2i_registry_access_redhat_com_ubi8_openjdk_11_1_20_2_1727147549_ac35a113" Config:{Hostname: Domainname: User:185 AttachStdin:false AttachStdout:true AttachStderr:false ExposedPorts:map[] Tty:false OpenStdin:true StdinOnce:true Env:[] Cmd:[/bin/sh -c tar -C /tmp -xf - && /usr/local/s2i/assemble] Healthcheck:<nil> ArgsEscaped:false Image:registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549 Volumes:map[] WorkingDir: Entrypoint:[] NetworkDisabled:false MacAddress: OnBuild:[] Labels:map[] StopSignal: StopTimeout:<nil> Shell:[]} HostConfig:&{Binds:[] ContainerIDFile: LogConfig:{Type: Config:map[]} NetworkMode: PortBindings:map[] RestartPolicy:{Name: MaximumRetryCount:0} AutoRemove:false VolumeDriver: VolumesFrom:[] ConsoleSize:[0 0] Annotations:map[] CapAdd:[] CapDrop:[] CgroupnsMode: DNS:[] DNSOptions:[] DNSSearch:[] ExtraHosts:[] GroupAdd:[] IpcMode: Cgroup: Links:[] OomScoreAdj:0 PidMode: Privileged:false PublishAllPorts:false ReadonlyRootfs:false SecurityOpt:[] StorageOpt:map[] Tmpfs:map[] UTSMode: UsernsMode: ShmSize:67108864 Sysctls:map[] Runtime: Isolation: Resources:{CPUShares:0 Memory:0 NanoCPUs:0 CgroupParent: BlkioWeight:0 BlkioWeightDevice:[] BlkioDeviceReadBps:[] BlkioDeviceWriteBps:[] BlkioDeviceReadIOps:[] BlkioDeviceWriteIOps:[] CPUPeriod:0 CPUQuota:0 CPURealtimePeriod:0 CPURealtimeRuntime:0 CpusetCpus: CpusetMems: Devices:[] DeviceCgroupRules:[] DeviceRequests:[] KernelMemory:0 KernelMemoryTCP:0 MemoryReservation:0 MemorySwap:0 MemorySwappiness:<nil> OomKillDisable:<nil> PidsLimit:<nil> Ulimits:[] CPUCount:0 CPUPercent:0 IOMaximumIOps:0 IOMaximumBandwidth:0} Mounts:[] MaskedPaths:[] ReadonlyPaths:[] Init:<nil>}} ...
I1203 20:02:49.592247 2137054 docker.go:1003] Attaching to container "eff6feda10f447c55997e6cfa8cdf600f78978bfda3c1eb8f8dbf271594125ef" ...
I1203 20:02:49.592596 2137054 docker.go:1014] Starting container "eff6feda10f447c55997e6cfa8cdf600f78978bfda3c1eb8f8dbf271594125ef" ...
I1203 20:02:50.041161 2137054 tar.go:336] Adding to tar: /tmp/s2i3625065130/upload/src as src
...
I1203 20:02:50.042803 2137054 tar.go:336] Adding to tar: /tmp/s2i3625065130/upload/src/src/main/webapp/WEB-INF/web.xml as src/src/main/webapp/WEB-INF/web.xml
I1203 20:02:50.064289 2137054 sti.go:717] INFO Performing Maven build in /tmp/src
I1203 20:02:50.064311 2137054 sti.go:717] INFO Using MAVEN_OPTS -XX:MaxRAMPercentage=80.0 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=25.0
I1203 20:02:50.236585 2137054 sti.go:717] INFO Using Apache Maven 3.8.5 (Red Hat 3.8.5-6)
I1203 20:02:50.236602 2137054 sti.go:717] Maven home: /usr/share/maven
I1203 20:02:50.236609 2137054 sti.go:717] Java version: 11.0.24, vendor: Red Hat, Inc., runtime: /usr/lib/jvm/java-11-openjdk-11.0.24.0.8-3.el8.x86_64
I1203 20:02:50.236616 2137054 sti.go:717] Default locale: en, platform encoding: UTF-8
I1203 20:02:50.236622 2137054 sti.go:717] OS name: "linux", version: "6.8.9-100.fc38.x86_64", arch: "amd64", family: "unix"
I1203 20:02:50.236628 2137054 sti.go:717] INFO Running 'mvn -e -Popenshift -DskipTests -Dcom.redhat.xpaas.repo.redhatga -Dfabric8.skip=true -Djkube.skip=true --batch-mode -Djava.net.preferIPv4Stack=true -s /tmp/artifacts/configuration/settings.xml -Dmaven.repo.local=/tmp/artifacts/m2 package'
I1203 20:02:51.271595 2137054 sti.go:713] [INFO] Error stacktraces are turned on.
I1203 20:02:51.347821 2137054 sti.go:713] [INFO] Scanning for projects...
I1203 20:02:51.417274 2137054 sti.go:713] [INFO]
I1203 20:02:51.417291 2137054 sti.go:713] [INFO] --------------------------< counter:counter >---------------------------
I1203 20:02:51.417310 2137054 sti.go:713] [INFO] Building counter 0.0.1-SNAPSHOT
I1203 20:02:51.417347 2137054 sti.go:713] [INFO] --------------------------------[ war ]---------------------------------
I1203 20:02:51.627771 2137054 sti.go:713] [INFO] Downloading from central: https://repo1.maven.org/maven2/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom
I1203 20:02:52.140387 2137054 sti.go:713] [INFO] Downloaded from central: https://repo1.maven.org/maven2/org/apache/maven/plugins/maven-resources-plugin/2.6/maven-resources-plugin-2.6.pom (8.1 kB at 15 kB/s)
I1203 20:02:52.154978 2137054 sti.go:713] [INFO] Downloading from central: https://repo1.maven.org/maven2/org/apache/maven/plugins/maven-plugins/23/maven-plugins-23.pom
...
...
...
I1203 20:03:13.388411 2137054 sti.go:713] [INFO] Downloaded from central: https://repo1.maven.org/maven2/org/codehaus/plexus/plexus-compiler-javac/2.8.4/plexus-compiler-javac-2.8.4.jar (21 kB at 29 kB/s)
I1203 20:03:13.456770 2137054 sti.go:713] [INFO] Changes detected - recompiling the module!
I1203 20:03:13.457563 2137054 sti.go:713] [WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
I1203 20:03:13.459769 2137054 sti.go:713] [INFO] Compiling 2 source files to /tmp/src/target/classes
I1203 20:03:14.051039 2137054 sti.go:713] [INFO]
I1203 20:03:14.051055 2137054 sti.go:713] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ counter ---
I1203 20:03:14.054788 2137054 sti.go:713] [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
I1203 20:03:14.054832 2137054 sti.go:713] [INFO] skip non existing resourceDirectory /tmp/src/src/test/resources
I1203 20:03:14.055146 2137054 sti.go:713] [INFO]
I1203 20:03:14.055185 2137054 sti.go:713] [INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ counter ---
I1203 20:03:14.063396 2137054 sti.go:713] [INFO] No sources to compile
I1203 20:03:14.063463 2137054 sti.go:713] [INFO]
I1203 20:03:14.063597 2137054 sti.go:713] [INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ counter ---
I1203 20:03:14.072343 2137054 sti.go:713] [INFO] Downloading from central: https://repo1.maven.org/maven2/org/apache/maven/maven-plugin-api/2.0.9/maven-plugin-api-2.0.9.pom
I1203 20:03:14.159197 2137054 sti.go:713] [INFO] Downloaded from central: https://repo1.maven.org/maven2/org/apache/maven/maven-plugin-api/2.0.9/maven-plugin-api-2.0.9.pom (1.5 kB at 17 kB/s)
...
....
I1203 20:03:22.088895 2137054 sti.go:713] [INFO] Downloaded from central: https://repo1.maven.org/maven2/xmlpull/xmlpull/1.1.3.1/xmlpull-1.1.3.1.jar (7.2 kB at 19 kB/s)
I1203 20:03:22.498224 2137054 sti.go:713] [INFO] Packaging webapp
I1203 20:03:22.499729 2137054 sti.go:713] [INFO] Assembling webapp [counter] in [/tmp/src/target/counter-0.0.1-SNAPSHOT]
I1203 20:03:22.510963 2137054 sti.go:713] [INFO] Processing war project
I1203 20:03:22.511126 2137054 sti.go:713] [INFO] Copying webapp resources [/tmp/src/src/main/webapp]
I1203 20:03:22.536258 2137054 sti.go:713] [INFO] Webapp assembled in [36 msecs]
I1203 20:03:22.566558 2137054 sti.go:713] [INFO] Building war: /tmp/src/target/counter-0.0.1-SNAPSHOT.war
I1203 20:03:22.597619 2137054 sti.go:713] [INFO] ------------------------------------------------------------------------
I1203 20:03:22.597632 2137054 sti.go:713] [INFO] BUILD SUCCESS
I1203 20:03:22.597637 2137054 sti.go:713] [INFO] ------------------------------------------------------------------------
I1203 20:03:22.598365 2137054 sti.go:713] [INFO] Total time: 31.279 s
I1203 20:03:22.598503 2137054 sti.go:713] [INFO] Finished at: 2024-12-04T01:03:22Z
I1203 20:03:22.598515 2137054 sti.go:713] [INFO] ------------------------------------------------------------------------
I1203 20:03:22.598607 2137054 sti.go:713] [WARNING] The requested profile "openshift" could not be activated because it does not exist.
I1203 20:03:22.687082 2137054 sti.go:717] INFO Copying deployments from target to /deployments...
I1203 20:03:22.694079 2137054 sti.go:717] INFO Cleaning up source directory (/tmp/src)
I1203 20:03:22.700875 2137054 docker.go:1045] Waiting for container "eff6feda10f447c55997e6cfa8cdf600f78978bfda3c1eb8f8dbf271594125ef" to stop ...
I1203 20:03:22.864217 2137054 docker.go:1070] Invoking PostExecute function
I1203 20:03:22.864243 2137054 postexecutorstep.go:68] Skipping step: store previous image
I1203 20:03:22.864249 2137054 postexecutorstep.go:117] Executing step: commit image
I1203 20:03:22.865447 2137054 postexecutorstep.go:523] Checking for new Labels to apply...
I1203 20:03:22.865457 2137054 postexecutorstep.go:531] Creating the download path '/tmp/s2i3625065130/metadata'
I1203 20:03:22.865491 2137054 postexecutorstep.go:465] Downloading file "/tmp/.s2i/image_metadata.json"
I1203 20:03:22.884669 2137054 postexecutorstep.go:539] unable to download and extract 'image_metadata.json' ... continuing
I1203 20:03:22.887105 2137054 docker.go:1104] Committing container with dockerOpts
...
release:2.1727147549 summary:Source To Image (S2I) image for Red Hat OpenShift providing OpenJDK 11 url:https://access.redhat.com/containers/#/registry.access.redhat.com/ubi8/openjdk-11/images/1.20-2.1727147549 usage:https://jboss-container-images.github.io/openjdk/ vcs-ref:f8db8e8d4a9162b6828f7d1674f58958a5bcd241 vcs-type:git vendor:Red Hat, Inc. version:1.20] StopSignal: StopTimeout:<nil> Shell:[]}
I1203 20:03:23.245766 2137054 postexecutorstep.go:393] Executing step: report success
I1203 20:03:23.245781 2137054 postexecutorstep.go:398] Successfully built openjdk-session:example
I1203 20:03:23.245786 2137054 postexecutorstep.go:93] Skipping step: remove previous image
I1203 20:03:23.245810 2137054 docker.go:981] Removing container "eff6feda10f447c55997e6cfa8cdf600f78978bfda3c1eb8f8dbf271594125ef" ...
I1203 20:03:23.294409 2137054 docker.go:991] Removed container "eff6feda10f447c55997e6cfa8cdf600f78978bfda3c1eb8f8dbf271594125ef"
I1203 20:03:23.294541 2137054 cleanup.go:33] Removing temporary directory /tmp/s2i3625065130
I1203 20:03:23.294548 2137054 fs.go:307] Removing directory '/tmp/s2i3625065130'
I1203 20:03:23.295113 2137054 build.go:182] Build completed successfullyOutput details
The following log messages describe each phase of the S2I build output and its purpose.
1. S2I toolkit version
Displays the version of the S2I toolkit currently in use.
Running S2I version "v1.5.1"2. Fetching builder image
Checks local cache for the builder image and fetches it from the registry using stored credentials.
Getting docker credentials for registry.access.redhat.com/ubi8/openjdk-17:latest
I0917 17:13:57.941059 3634108 docker.go:511] Using locally available image "registry.access.redhat.com/ubi8/openjdk-17:latest"3. S2I build configuration
Provides the core build details and parameter configurations for the image build process.
build.go:170]
Builder Name: Java Applications
Builder Image: registry.access.redhat.com/ubi8/openjdk-17:latest
Source: hotrodspringboot/
Output Image Tag: openjdk-hotrod:example
Environment:
Labels:
Incremental Build: disabled
Remove Old Build: disabled
Builder Pull Policy: if-not-present
Previous Image Pull Policy: if-not-present
Quiet: disabled
Layered Build: disabled
Docker Endpoint: unix:///var/run/docker.sock
Docker Pull Config: /root/.docker/config.json
Docker Pull User: 4. Source repository checkout
Clones the source repository into a temporary directory and checks out the designated Git commit/branch.
I0917 17:13:57.948617 3634108 clone.go:41] Cloning sources into "/tmp/s2i3705874102/upload/src"
I0917 17:13:57.995712 3634108 clone.go:57] Checked out "HEAD"
I0917 17:13:58.025261 3634108 clone.go:63] Updated submodules for "HEAD"5. Container configuration
Defines runtime options, environment variables, entry points, and resource constraints for the build container.
I0917 17:13:58.044736 3634108 docker.go:991] Creating container with options {Name:"s2i_registry_access_redhat_com_ubi8_openjdk_17_latest_c6463743" Config:{Hostname: Domainname: User:185 AttachStdin:false AttachStdout:true AttachStderr:false ExposedPorts:map[] Tty:false OpenStdin:true StdinOnce:true Env:[] Cmd:[/bin/sh -c tar -C /tmp -xf - && /usr/local/s2i/assemble] Healthcheck: ArgsEscaped:false Image:registry.access.redhat.com/ubi8/openjdk-17:latest Volumes:map[] WorkingDir: Entrypoint:[] NetworkDisabled:false MacAddress: OnBuild:[] Labels:map[] StopSignal: StopTimeout: Shell:[]} HostConfig:&{Binds:[] ContainerIDFile: LogConfig:{Type: Config:map[]} NetworkMode: PortBindings:map[] RestartPolicy:{Name: MaximumRetryCount:0} AutoRemove:false VolumeDriver: VolumesFrom:[] ConsoleSize:[0 0] Annotations:map[] CapAdd:[] CapDrop:[] CgroupnsMode: DNS:[] DNSOptions:[] DNSSearch:[] ExtraHosts:[] GroupAdd:[] IpcMode: Cgroup: Links:[] OomScoreAdj:0 PidMode: Privileged:false PublishAllPorts:false ReadonlyRootfs:false SecurityOpt:[] StorageOpt:map[] Tmpfs:map[] UTSMode: UsernsMode: ShmSize:67108864 Sysctls:map[] Runtime: Isolation: Resources:{CPUShares:0 Memory:0 NanoCPUs:0 CgroupParent: BlkioWeight:0 BlkioWeightDevice:[] BlkioDeviceReadBps:[] BlkioDeviceWriteBps:[] BlkioDeviceReadIOps:[] BlkioDeviceWriteIOps:[] CPUPeriod:0 CPUQuota:0 CPURealtimePeriod:0 CPURealtimeRuntime:0 CpusetCpus: CpusetMems: Devices:[] DeviceCgroupRules:[] DeviceRequests:[] KernelMemory:0 KernelMemoryTCP:0 MemoryReservation:0 MemorySwap:0 MemorySwappiness: OomKillDisable: PidsLimit: Ulimits:[] CPUCount:0 CPUPercent:0 IOMaximumIOps:0 IOMaximumBandwidth:0} Mounts:[] MaskedPaths:[] ReadonlyPaths:[] Init:}} ..6. Maven build execution
Applies JVM runtime settings (MAVEN_OPTS) and executes the packaging command with OpenShift options.
I0917 17:13:58.414210 3634108 sti.go:717] INFO Using MAVEN_OPTS -XX:MaxRAMPercentage=80.0 -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=25.0
I0917 17:13:58.557962 3634108 sti.go:717] OS name: "linux", version: "7.1.10-100.fc43.x86_64", arch: "amd64", family: "unix"
I0917 17:13:58.557975 3634108 sti.go:717] INFO Running 'mvn -e -Popenshift -DskipTests -Dcom.redhat.xpaas.repo.redhatga -Dfabric8.skip=true -Djkube.skip=true --batch-mode -Djava.net.preferIPv4Stack=true -s /tmp/artifacts/configuration/settings.xml -Dmaven.repo.local=/tmp/artifacts/m2 package'
I0917 17:13:59.086314 3634108 sti.go:713] [INFO] Error stacktraces are turned on.7. Application compilation
Target project details and artifact packaging initialization.
I0917 17:14:03.717038 3634108 sti.go:713] [INFO] -----------------< com.redhat.hotrod:hotrodspringboot >-----------------
I0917 17:14:03.717046 3634108 sti.go:713] [INFO] Building hotrodspringboot 0.0.1-SNAPSHOT
I0917 17:14:03.717051 3634108 sti.go:713] [INFO] --------------------------------[ jar ]---------------------------------8. Build success and deployment
Confirms successful artifact build, moves the compiled .jar file to /deployments, cleans build artifacts, and halts the build container.
I0917 17:15:42.823591 3634108 sti.go:713] [INFO] Replacing main artifact with repackaged archive
I0917 17:15:42.823685 3634108 sti.go:713] [INFO] ------------------------------------------------------------------------
I0917 17:15:42.823697 3634108 sti.go:713] [INFO] BUILD SUCCESS
I0917 17:15:42.823702 3634108 sti.go:713] [INFO] ------------------------------------------------------------------------
I0917 17:15:42.824836 3634108 sti.go:713] [INFO] Total time: 01:43 min
I0917 17:15:42.824999 3634108 sti.go:713] [INFO] Finished at: 2026-09-17T21:15:42Z
I0917 17:15:42.825008 3634108 sti.go:713] [INFO] ------------------------------------------------------------------------
I0917 17:15:42.908276 3634108 sti.go:717] INFO Copying deployments from target to /deployments...
I0917 17:15:42.937355 3634108 sti.go:713] '/tmp/src/target/hotrodspringboot-0.0.1-SNAPSHOT.jar' -> '/deployments/hotrodspringboot-0.0.1-SNAPSHOT.jar'
I0917 17:15:42.946276 3634108 sti.go:717] INFO Cleaning up source directory (/tmp/src)
I0917 17:15:42.983229 3634108 docker.go:1072] Waiting for container "63b6dbe1a9bb16493f3e1ddc1bd75b97d06de3d09baec9b4c6b2f20e09bcedf1" to stop ...BuildConfig example 3: Custom run-java.sh
In some cases, the default run-java.sh script included with the OpenJDK image might not meet specific application requirements. The following command displays the default runtime configuration:
$ podman run --cpus 3 --memory=1000m --rm -it localhost/quarkus-image:latest
INFO exec java -XX:+UseParallelOldGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:MaxMetaspaceSize=100m -XX:+ExitOnOutOfMemoryError -cp "." -jar /deployments/quarkust-test-1.0.0-SNAPSHOT-runner.jar -jar quarkust-test-1.0.0-SNAPSHOT-runner.jar -DanexampleA custom run-java.sh script can specify G1GC or Shenandoah as the garbage collector instead of the default ParallelGC. To replace run-java.sh when using S2I, deploy a custom script to /deployments/bin/run.sh in the image. The container will launch this custom script instead.
Review the custom run-java.sh repository for a complete example.
Notes on certificate injection in Java applications
Once you build your container image locally, deploying it to a secure OpenShift cluster often requires handling TLS trust stores. Java applications require certificate injection to establish secure connections at build time or runtime.
Build-time injection is straightforward as long as the certificate file is accessible and building the container (for example, using Dockerfile injection) is feasible. For runtime injection, you can use 3 methods across 2 operators:
| Component | Method | How to do it |
|---|---|---|
service-ca operator | Injection via ConfigMap annotation | Create a ConfigMap and add a specific annotation so users can access that certificate. |
service-ca operator | Injection via service annotation | Create a service and add a specific annotation; a Secret will be created for the deployment to use. |
cert-manager 0perator | Installing an operator that allows certificate creation | Install the cert-manager operator. The user creates an Issuer and Certificate custom resource (CR). cert-manager creates a Secret containing the resulting certificate so the application can access it. |
The service-ca operator, which comes with OpenShift 4.x clusters, only helps with injection. Executing update-ca-trust with the extract argument (for Java KeyStore (JKS) creation) requires the root user.
The service-ca operator does not provide a specific option for JKS injection, whereas cert-manager can create a JKS keystore when generating the certificate and store it directly in the Secret.
Troubleshooting
Use the following guidance to resolve common issues when building application images locally with S2I.
S2I tool not installed: Install s2i tool
If the S2I tool is not installed on your system, running the build command prompts package installation:
$ s2i --loglevel 5 build SessionReplication/ registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549 openjdk-session:example
bash: s2i: command not found...
Install package 'source-to-image' to provide command 's2i'? [N/y] y
* Waiting in queue...
* Loading list of packages....
The following packages have to be installed:
source-to-image_1.5.1-1.fc43.x86_64 A tool for building artifacts from source and injecting into container images
Proceed with changes? [N/y] y
* Waiting in queue...
* Waiting for authentication...
* Waiting in queue...
* Downloading packages...
* Requesting data...
* Testing changes...
* Installing packages...
I0917 16:11:14.726595 3616882 build.go:52] Running S2I version "v1.5.1"S2I tool Docker not running: Start Docker
If the Docker daemon is not running when you execute an S2I build, the command returns a connection error:
$ s2i --loglevel 5 build SessionReplication/ registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549 openjdk-session:example
I0917 16:11:17.794393 3616905 build.go:52] Running S2I version "v1.5.1"
I0917 16:11:17.794509 3616905 util.go:70] Getting docker credentials for registry.access.redhat.com/ubi8/openjdk-11:1.20-2.1727147549
F0917 16:11:17.794723 3616905 build.go:161] Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?Verify build finished
The S2I process executes a standard Maven build; it packages your application but does not automatically convert a standard WAR file into an executable JAR unless configured in your pom.xml file or build scripts.
Socket or permission errors during build
If you encounter socket or permission errors during local S2I builds, ensure your user account has access to the local container engine daemon or explicitly specify build permissions using --assemble-user.
Conclusion
The S2I standalone toolkit helps build container images locally, complementing Red Hat OpenShift builds where you provide commands through the oc CLI or create builds directly using YAML files.
| Method | Description | Pros | Cons |
|---|---|---|---|
| S2I standalone build | Local build | Easy local build with simple settings | Image must be uploaded to the cluster |
| OpenShift BuildConfig | Build on cluster | Easy cluster build with simple settings via YAML | Image must be downloaded locally; YAML requires more setup than the command line |
Additional resources
Watch the video guides on the Red Hat OpenShift YouTube channel for visual walkthroughs of these core concepts. See the article How to use Java container awareness in OpenShift 4 for details on container awareness and How does cgroups v2 impact Java, .NET, and Node.js in OpenShift 4? for cgroups v2.
Have questions about customizing S2I builders or converting local S2I options into cluster BuildConfigs? Connect with fellow developers on the Red Hat Developer community, test your newly built images in the no-cost Developer Sandbox, or open a ticket with Red Hat Support if you need assistance.
Special thanks to Alexander Barbosa for his contributions to this article and years of partnership at Red Hat.