DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workkloads.

Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Manage Microservices With Docker Compose
  • 5 Simple Tips to Keep Dockerized Apps Secure
  • Build and Deploy a Flask Application Using Docker
  • How To Dockerize Mean Stack App

Trending

  • Internal Developer Portals: Modern DevOps's Missing Piece
  • Beyond Linguistics: Real-Time Domain Event Mapping with WebSocket and Spring Boot
  • Unlocking AI Coding Assistants Part 1: Real-World Use Cases
  • How to Practice TDD With Kotlin
  1. DZone
  2. Software Design and Architecture
  3. Cloud Architecture
  4. How to Create a Builder Image With S2I

How to Create a Builder Image With S2I

For the eaiser crafting of Docker images from source code.

By 
Hüseyin Akdoğan user avatar
Hüseyin Akdoğan
DZone Core CORE ·
Updated Nov. 20, 18 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
18.0K Views

Join the DZone community and get the full member experience.

Join For Free

 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 USER=1001
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" \
      io.openshift.s2i.scripts-url="image://$S2IDIR/bin"

COPY s2i $S2IDIR
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/*

WORKDIR $APPDIR

EXPOSE 8080

USER $USER

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_")
        buildFileDirectory=$root_project_buildFileDirectory
        execCommand=$root_project_execCommand
        if [ ! -z "$buildFileDirectory" ]; then cd $buildFileDirectory; fi
fi

pomfile=pom.xml
gradlefile=build.gradle
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" ];
       then
            echo $message
            mv ./target/*.jar ./
   fi
elif [ -f $gradlefile ]; then
    echo "---> Gradle build detected..."
    gradle build
    if [ -z "$execCommand" ];
        then
            echo message
            mv ./build/libs/*.jar ./
     fi
fi

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" ];
    then
        jarName="*.jar"
    else
        eval $(parse_yaml $sfpath/setting.yml "root_")
        jarName=$root_project_jarName
        arguments=${root_project_arguments//['[',']']/''}
        outputDirectory=$root_project_outputDirectory
        execCommandWorkDir=$root_project_execCommandWorkDir
        execCommand=$root_project_execCommand
        if [ -z "$jarName" ]; then jarName="*.jar"; fi
fi

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

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

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

Conclusion

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.


Docker (software) application Build (game engine)

Opinions expressed by DZone contributors are their own.

Related

  • Manage Microservices With Docker Compose
  • 5 Simple Tips to Keep Dockerized Apps Secure
  • Build and Deploy a Flask Application Using Docker
  • How To Dockerize Mean Stack App

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!