Source-to-Image (S2I): building container images from source without a Dockerfile
A tool for building artifacts from source and injecting into container images
At a glance
- What is it?
- S2I is an OpenShift toolkit that injects application source into a builder image, runs an assemble script inside the container, and commits the result. It rewards teams that already treat build environments as versioned images, and it is the wrong tool for anyone who wants an ordinary Dockerfile workflow.
- Who is it for?
- Adopt S2I if your build environment is already a versioned container image and you want the same JDK or interpreter at build and run time without shipping compilers to production. Skip it if your team lives in Dockerfiles and expects multi-stage builds to cover the same ground, because S2I pushes that logic into image scripts you now have to write and maintain.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What S2I replaces, and why the Dockerfile is the thing it argues against
Source-to-Image produces ready-to-run images by injecting source code into a container image and letting the container prepare that source code for execution. The README frames this as a workflow for reproducible builds: instead of writing a Dockerfile that describes how to assemble an application, you pick a builder image that already knows how. The builder image carries the language runtime, the package manager, the web server and the build scripts. The application source is the only input that varies.
The stated goals are reproducibility, flexibility, speed and security. The security argument is the most concrete one in the README. Dockerfiles are described as running without many of the normal operational controls of containers, usually as root and with access to the container network. S2I launches the build in a single container, which means the platform can constrain what permissions and privileges the builder image gets. That is a real difference in the trust model, not a marketing line.
The audience is therefore narrower than "anyone building containers". S2I suits platform teams that want to hand developers a fixed set of approved builder images, and it suits anyone who needs the same runtime at build time and at run time. If you are happy writing and reviewing Dockerfiles yourself, S2I adds a layer you did not ask for.
The assemble, run and save-artifacts contract inside a builder image
A builder image is an ordinary container image with a small script contract. According to the README, s2i looks for four scripts: assemble, which builds or deploys the source; run, which runs the assembled artifacts; save-artifacts, which is optional and captures artifacts from a previous build for the next incremental build; and usage, also optional, which displays builder image usage information. The README also suggests that images provide /bin/sh and tar for the best experience, which is a hint about how the source gets in.
The build workflow is where the mechanism becomes visible. s2i creates a container from the build image and passes it a tar file containing the application source under src and, when applicable, build artifacts under artifacts. The source excludes anything matched by .s2iignore. s2i then sets environment variables from .s2i/environment, starts the container and runs its assemble script, waits for the container to finish, commits the container, sets the CMD of the output image to the run script, and tags the image with the name you provided.
So the data flow is: local or remote source tree, filtered by .s2iignore, tarred into the container, transformed by assemble, committed as an image whose entrypoint is run. Nothing about the application is described in a Dockerfile. The description lives in the builder image scripts, which is exactly the trade-off: you version the build logic as an image, and you write shell instead of Dockerfile instructions.
Installing s2i and running a first build against a Python builder image
The README points to the latest release on GitHub for downloads and gives a two-command example. There is no package manager instruction in the README, so the release page is the place to get the binary. The README example builds from a git repository URL, uses the centos/python-35-centos7 builder image, and tags the output hello-python:
$ s2i build https://github.com/sclorg/django-ex centos/python-35-centos7 hello-python
$ docker run -p 8080:8080 hello-pythonAfter the second command, the README says to browse to http://localhost:8080 to see the running application. What you should see is a built image tagged hello-python whose CMD is the builder image's run script, serving the Django example on port 8080.
The build reads the source tree, applies any .s2iignore rules in the repository root, and injects the result into the container. If you want to control the environment the assemble script sees, the README documents a .s2i/environment file in the source tree whose variables s2i sets before starting the container. The .s2iignore format is one rule per line, each line terminated by a newline, with file paths appended to the absolute path of the source tree root and wildcards allowed. Both files are read from the source repository, not from the builder image.
Where S2I gets awkward: incremental builds and the two-step pattern
The most interesting limitation is not a bug, it is a design consequence. For compiled languages the README is explicit that dependencies needed for compilation can dramatically outweigh the runtime artifacts. The answer is a multiple-step build: create a builder image with OpenJDK and Tomcat that expects a WAR file, create a second image layering Maven on top that expects a Maven project, run s2i with the application source and the Maven image to produce the WAR, then run s2i a second time with that WAR and the Tomcat image to produce the runtime image. That is four moving parts and two invocations for what a multi-stage Dockerfile expresses in one file.
Incremental builds depend on save-artifacts, which the README lists as optional. If your builder image does not implement it, there is nothing to capture between builds, and the artifacts directory in the tar file will not be populated. The README does not document rollback of a committed image, nor does it describe how a failed assemble leaves the working container, so error handling is left to the scripts you write.
None of this makes S2I wrong. It does mean the cost lands on whoever maintains the builder images. Writing assemble and run scripts that behave correctly for every application your platform hosts is more work than maintaining one Dockerfile per service, and the README's own tutorial points to examples/nginx-centos7 for a practical walkthrough rather than claiming the scripts are trivial.
S2I compared with a multi-stage Dockerfile
The closest real alternative is a multi-stage Dockerfile, and the difference is where the build logic lives. A multi-stage Dockerfile keeps the build recipe in the repository next to the application, versioned with the code that it builds. S2I moves that recipe into the builder image, versioned separately and shared across applications. The README's speed goal follows from this: rather than building multiple layers in a single Dockerfile, S2I encourages representing an application in a single image layer, which the README says saves time during creation and deployment.
The trade-offs run in both directions. A multi-stage Dockerfile gives you per-application control and a plain text diff when the build changes. S2I gives you a fixed interface (source in, image out) that a platform can police, which is what makes the privilege story workable. If your organization needs to limit what developers can do at build time, the Dockerfile approach makes that harder because the build recipe is arbitrary and developer-owned. If your organization needs per-service build tweaks, S2I makes that harder because the tweaks belong in a shared image.
There is also a practical difference in what you can test locally. A Dockerfile builds with docker build and nothing else. An S2I build requires the s2i binary and a builder image that satisfies the script contract, so the failure modes are split between the tool and the image.
Maintenance, releases and the Apache-2.0 licence
The repository is not archived, and the last push was on 2026-09-28. The most recent release listed is v1.6.4 from 2026-09-22, following v1.6.3 in July 2026 and v1.6.2 in June 2026. That cadence suggests the project is still receiving fixes, though the README does not describe a support policy or a deprecation timeline for older builder images.
Upgrade cost mostly sits in the builder images rather than the s2i binary. The tool's interface is the script contract and the .s2iignore and .s2i/environment files, and the README does not document a versioning scheme for that contract. If you maintain builder images, you are the one who decides when to rebuild them on a new base image, and the README gives no migration guidance for doing so.
The project is licensed Apache-2.0, and the repository carries a LICENSE file at the top level. The README does not discuss patent grants, attribution requirements or compatibility with other licences, so treat the licence text itself as the source of truth rather than this summary. Nothing here is legal advice.
Editorial conclusion
Adopt S2I if your build environment is already a versioned container image and you want the same JDK or interpreter at build and run time without shipping compilers to production. Skip it if your team lives in Dockerfiles and expects multi-stage builds to cover the same ground, because S2I pushes that logic into image scripts you now have to write and maintain. Before committing, verify that your builder image ships the assemble and run scripts s2i expects, and check whether it also provides save-artifacts if you want incremental builds.
Frequently asked questions
How does OpenShift source-to-image work?
s2i creates a container from a builder image, injects the application source as a tar file under src, sets environment variables from .s2i/environment, runs the image's assemble script, then commits the container with the CMD set to the run script and tags it with the name you gave.
What is source-to-image in OpenShift?
It is a toolkit and workflow for building reproducible container images from source code, where the build logic lives in a builder image rather than a Dockerfile. The README describes it as producing ready-to-run images by injecting source into a container and letting the container prepare that source for execution.
How do I get s2i and run a first build?
The README directs you to the latest release on GitHub for the download, then shows s2i build with a git repository URL, a builder image such as centos/python-35-centos7, and an output image name, followed by docker run to start the result.
What scripts does an S2I builder image need?
The README lists assemble, which builds or deploys the source, and run, which runs the assembled artifacts, as the required pair. save-artifacts and usage are optional, and the README suggests images also provide /bin/sh and tar.
How do I exclude files from an S2I build?
Place a .s2iignore file in the root of the source repository with one rule per line, each line terminated by a newline. File paths are appended to the absolute path of the source tree root, and wildcards and globbing are allowed.
Why would an S2I build use two steps instead of one?
For compiled languages the README notes that compilation dependencies can greatly outweigh the runtime artifacts, so S2I supports building a binary or WAR in one builder image and injecting it into a second, slimmer runtime image that only places the artifact for execution.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/openshift-source-to-image)