The S2I scripts are packaged within the S2I builder images by default. In certain scenarios, you may want to customize these scripts to change the way your application is built and run, without rebuilding the image.
The S2I build process provides a method to override the default S2I scripts.
You can provide your own S2I scripts in the .s2i/bin folder of the application source code.
During the build process, the custom S2I scripts are automatically detected and run instead of the default S2I scripts packaged in the builder image.
Depending on the amount of customization that needs to be done to the overridden scripts, you may choose to completely replace the default S2I scripts with your own version. Alternatively, you can create a wrapper script that invokes the default scripts, and then adds the necessary customization before or after the invocation.
For example, suppose you want to customize the S2I scripts for the rhscl/php-73-rhel7 S2I builder image, and change the way the application is built and run.
You can use the following procedure to customize the S2I scripts provided in this builder image:
Use the podman pull command to pull the container image from a container registry to the local system.
Use the podman inspect command to get the value of the io.openshift.s2i.scripts-url label, to determine the default location of the S2I scripts in the image.
[user@host ~]$podman pull \ myregistry.example.com/rhscl/php-73-rhel7...output omitted... Digest: sha256:... [user@host ~]$podman inspect \ --format='{{ indeximage:///usr/libexec/s2i.Config.Labels"io.openshift.s2i.scripts-url"}}' \ rhscl/php-73-rhel7
You can also use the skopeo inspect command to retrieve the same information directly from a remote registry:
[user@host ~]$ skopeo inspect \
docker://myregistry.example.com/rhscl/php-73-rhel7 \
| grep io.openshift.s2i.scripts-url
"io.openshift.s2i.scripts-url": "image:///usr/libexec/s2i",Create a wrapper for the assemble script in the .s2i/bin folder:
#!/bin/bash
echo "Making pre-invocation changes..."
/usr/libexec/s2i/assemble
rc=$?
if [ $rc -eq 0 ]; then
echo "Making post-invocation changes..."
else
echo "Error: assemble failed!"
fi
exit $rcSimilarly, create a wrapper for the run script in the .s2i/bin folder:
#!/bin/bash echo "Before calling run..." exec /usr/libexec/s2i/run
When wrapping the run script, you must use exec to invoke it.
This ensures that the default run script still runs with a process ID of 1.
Failure to do this results in signal propagation errors during shutdown, and your application may not work correctly.
This also implies that you cannot run additional commands in the wrapper script after invoking the default run script.
When building applications on Red Hat OpenShift by using S2I, it is common to build, deploy, and test small incremental changes to your applications. Certain organizations have adopted continuous integration (CI) and continuous delivery (CD) techniques, where the application is built and deployed multiple times in a rapid iterative cycle, often without any manual intervention.
When your application is built in a modular fashion with several dependent components and libraries, S2I builds take up a lot of time due to the immutable nature of containers. The build process must fetch the dependencies and then build and deploy the application every time there is a change to the source code.
The S2I build process provides a mechanism to reduce build time by invoking the save-artifacts script after invoking the assemble script, as part of the S2I life cycle.
The save-artifacts script ensures that dependent artifacts (libraries and components required for the application) are saved for future builds.
During the next build, the assemble script restores the cached artifacts before building the application from source code.
Note that the save-artifacts script is responsible for streaming dependencies to a tar file via standard output.
The save-artifacts script output should only include the tar stream output, and nothing else.
You should redirect output of other commands in the script to /dev/null.
For example, assume that you are developing a Java EE-based application with many dependencies managed by using Apache Maven.
Assuming that you have built an S2I builder image where the assemble script compiles and packages the application JAR file, incremental builds that can reuse previously downloaded JAR files reduce the build time by a large margin.
Apache Maven stores JAR dependencies in the $HOME/.m2 folder.
The save-artifacts script that caches Maven JAR files can be defined as follows:
#!/bin/sh -e
# Stream the .m2 folder tar archive to stdout
if [ -d ${HOME}/.m2 ]; then
pushd ${HOME} > /dev/null
tar cf - .m2
popd > /dev/null
fiThe corresponding code to restore the artifacts before building is in the following assemble script:
# Restore the .m2 folder ...output omitted... if [ -d /tmp/artifacts/.m2 ]; then echo "---> Restoring maven artifacts..." mv /tmp/artifacts/.m2 ${HOME}/ fi ...output omitted...
Further information is available in the Creating Images chapter of the Images guide for Red Hat OpenShift 4.12 at https://access.redhat.com/documentation/en-us/openshift_container_platform/4.12/html-single/images/index#creating-images