How to Create a Builder Image With S2I

DZone 's Guide to

How to Create a Builder Image With S2I

For the eaiser crafting of Docker images from source code.

· Cloud Zone ·
Free Resource

 Source-To-Image  (S2I) is a standalone toolkit and workflow for creating builder images. It allows you to build reproducible Docker  images from source code. The magic of the S2I is to produce ready-to-run images by injecting source code into a Docker container. This means that the builder image contains the specific intelligence required to produce that executable image based on the source code and you can have reusable dynamic images for creating build and runtime environments based on your needs.

The S2I project includes some ready-to-use builder images. You can extend these images and also create your own images.

How to Create an S2I Builder Image

An S2I builder image basically should contain assemble  and run   scripts besides a Docker file. In addition, it may include optional save-artifacts   and usage  scripts. Responsibilities of these scripts are:

  •  assemble – It is responsible for the build of the application that given as input

  •  run – It is responsible for running the application

  •  save-artifacts  – It is responsible for incremental builds

  •  usage – It is responsible for printing the usage of The builder image

After downloading the application source which is given as an input, S2I streams these scripts and the source into the builder image container and then runs the assemble script.

Let's Create Our Builder Image

Suppose we need a builder to speed up build and deployment process for our team. The builder should support Maven  and Gradle  projects, execute regular jars, even be able to pass arguments when wanted, in addition, allows configuring with environment variables.

For the mentioned requirements, we must first define the Dockerfile.

FROM ubuntu:latest

ARG S2IDIR="/home/s2i"
ARG APPDIR="/deployments"

LABEL maintainer="Huseyin Akdogan <hakdogan@kodcu.com>" \
      io.k8s.description="S2I builder for Java Applications." \
      io.k8s.display-name="Handy Environment" \
      io.openshift.expose-services="8080:http" \
      io.openshift.tags="builder,java,maven,gradle" \

RUN chmod 777 -R $S2IDIR

COPY jdkinstaller.sh "$APPDIR/"
COPY parse_yaml.sh "$APPDIR/"

RUN useradd $USER \
    && chown $USER:$USER $APPDIR \
    && addgroup $USER $USER \
    && chmod 777 -R $APPDIR

RUN apt-get update -y && \
    apt-get install -y software-properties-common

RUN ["/bin/bash", "-c", "$APPDIR/jdkinstaller.sh"]

RUN apt-get install maven -y && \
    apt-get install -y unzip && \
    apt-get install -y wget && \
    wget https://services.gradle.org/distributions/gradle-4.10.2-bin.zip && \
    mkdir /opt/gradle && \
    unzip -d /opt/gradle gradle-4.10.2-bin.zip && \
    ls /opt/gradle/gradle-4.10.2

ENV PATH=$PATH:/opt/gradle/gradle-4.10.2/bin
RUN rm -rf /var/lib/apt/lists/*




CMD ["$S2IDIR/bin/run"]

We specify that we want to have JDK , Maven  and Gradle  in the container with the Dockerfile. The jdkinstaller.sh file contains the logic of downloading the desired version of JDK based on the related environment variable. Also, along with labels for promotion the application, we defined the location of the scripts inside of the builder image with the value of the io.openshift.s2i.scripts-url label. In the last line, we set the default CMD to execute the run script when the container was run.

 Assemble  script:

#!/bin/bash -e

set -e

echo "---> Installing application source..."
cp -Rf /tmp/src/. ./

. parse_yaml.sh
if [ ! -z "$sfpath" ]; then
        eval $(parse_yaml $sfpath/setting.yml "root_")
        if [ ! -z "$buildFileDirectory" ]; then cd $buildFileDirectory; fi

message="---> Moving the jar file(s) to the main application directory..."

if [ -f $pomfile ]; then
   echo "---> Maven build detected..."
   mvn clean install  -Dmaven.repo.local=/tmp/artifacts/m2 -DskipTests -Dfabric8.skip=true -Djava.net.preferIPv4Stack=true
   if [ -z "$execCommand" ];
            echo $message
            mv ./target/*.jar ./
elif [ -f $gradlefile ]; then
    echo "---> Gradle build detected..."
    gradle build
    if [ -z "$execCommand" ];
            echo message
            mv ./build/libs/*.jar ./

As we mentioned,  assemble script is responsible for the build of the application that given as input. The script contains the logic required to meet this need. By default, S2I places the application source in the /tmp/src directory. Hence, we first copy the resource files to the WORKDIR   that we defined in the Dockerfile.

Then, the script looking for a build configuration file belonging to Maven  or Gradle . If the file exists and the execCommand  not defined, the required commands are executed and the created jar is moved to the WORKDIR . This jar will be executed by the  run script .

 Run script :

#!/bin/bash -e

set -e

. parse_yaml.sh

if [ -z "$sfpath" ];
        eval $(parse_yaml $sfpath/setting.yml "root_")
        if [ -z "$jarName" ]; then jarName="*.jar"; fi

if [ ! -z "$outputDirectory" ]; then cd $outputDirectory; fi

if [ ! -z "$execCommand" ]; then
    if [ ! -z "$execCommandWorkDir" ]; then cd $execCommandWorkDir; fi
    exec $execCommand
    java -jar $jarName $arguments

The script calls the parse method for the setting.yml  file if provided. The file is used to define custom requirements such as jar name or arguments. Finally, the command required to run the application is executed. 

That's it.

You can access the source code of that builder from this repository.

To Build

You should run following command.

oc new-build $builder_path_or_url \
--name jdk-container

After the build process is successful, you can pass your source code as an input to the builder image as follows.

oc new-app jdk-container~$repo_path_or_url


The S2I is a powerful and useful tool that can produce ready-to-run images by injecting source code into a Docker container. In addition to includes some ready-to-use builder images such as Java, or Ruby, or Python it also allows to extend these images and also create your own images. You can speed up the build and deployment processes using S2I for your team.

cloud, docker, docker image, openshift, source code, tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}