Source-To-Image: Getting Started With s2i

Image for post
Image for post

When I first began learning OpenShift two years ago, I was immediately struck by how easy it was to build really simple applications, especially when you were building in Java on JBoss or WildFly. You could literally create a project with just one command and it would generate everything you needed:

As I’ve talked about in my entry on OpenShift on the command line, the new-app command creates a number of Kubernetes resources for you. The command I’ve used here though is slightly different. In that blog entry, I only specified an image, and a basic one at that:

So what’s different here? The difference is that I’m not only specifying an image, I’m specifying a code repository. The image that I’m specifying is not the image that will get deployed, but rather a base image upon which we will build our final image. OpenShift creates a build config resource that references both the base image and the source repo so that OpenShift knows how to build our target image. When a build is initiated, the source is pulled from the repo, compiled (it knows how to compile Java code if you are using Maven, for example), and a new image is created that extends the base image with the built code placed where it needs to be. As I’ll show later, you can also specify a built binary or a directory either containing source or a built binary. If what I specify is a binary, it just skips the step of building the code.

This was all really cool. It made it so that I could easily demo OpenShift to interested parties and literally get the project built and deployed in two commands (the first step was the new-app step shown above, the second step was to kick off a build which would automatically kick off a deploy of the built image). I dug into how OpenShift was doing this, and that is when I discovered that this actually wasn’t something built into OpenShift. It was actually a separate tool called s2i, which stands for source-to-image.

Introducing s2i

You can think of the s2i tool as essentially being an alternative to Dockerfiles for building Docker images. It is an open source tool, and you can find the source on github. s2i is written in Go, the same language that was used to build the kubectl and oc command line tools used for Kubernetes and OpenShift. You just need to have Docker installed if you download the binary of s2i, but you can also build it from source if you have Go installed.

Technically, s2i can work with any base image, but it is intended to work with images that are commonly called builder images, which is to say that they have code inside of them that the s2i tool uses to do its job. This is intentional, because often when you are using these builder images, how your code gets deployed is related to what base image you are using. In my above example, I used a JBoss EAP 7 image that was bundled with OpenShift. This image has some s2i code inside that knows how to build a Java war or ear project if it uses a common build tool like Maven.

A Simple Example

If you have s2i installed, you can easily see this work. For the purposes of this example, I’ll deploy on a JBoss EAP 7 image pulled from Red Hat’s developer registry. You can sign up for a developer account on Red Hat’s developer site to get access to this registry (not to mention lots of other developer tools and resources that Red Hat gives out for free). Once you are signed up, you first need to login to the registry:

Next I will pull the JBoss EAP 7 image, the same one that gets bundled with OpenShift:

I’ve stolen borrowed an example helloworld application for demonstrating deploying a simple app onto JBoss using s2i, and so without further ado, we can build the image with a simple command:

This will take a little while, but when the build is complete, you can see the image you created is now in the Docker registry:

Simply running the image like we would any other Docker image is straightforward, and you will see the usual JBoss startup logging, with a message at the bottom telling us our war has been deployed (I’ve mapped the JBoss 8080 port to 9080 to avoid a port conflict on my host):

Now if we curl the localhost, we can see our app running (the URL path is localhost:9080/helloworld, which sends back a meta refresh to /helloworld/HelloWorld, so I’m just skipping the refresh here):

As I mentioned before, you can use a git repo to specify the source, but you can also specify a directory where the source is as well. I have the repository cloned locally, so I can just run this to build the image:

I can also specify just the pre-compiled war so that I can skip the compile step:

Conclusion

In this article I discussed the basics of using the s2i tool to build images. There is a lot more it can do, such as customizing the build steps, caching build artifacts, customizing how the process in the container is run, etc. I will try to talk about these features in a future article.

Originally published on July 3, 2018.

Written by

I'm a technology enthusiast, always searching for better ways of doing things. Lately that has been all things React. I also write a lot on Medium. :)

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store