Using S2i (source-to-image) like buildpacks to deploy apps
Openshift’s S2i (Source-2-image) is an alternative framework to buildpacks which uses Dockerfiles and Openshift to create applications out of reproducible container images from source.
Objective
The goal is to be able to create a container image that contains the necessary application dependencies just by uploading the application code without having to write Dockerfiles.
Creating S2i builder images
S2i builder images are the base images that your deploying application will be injected its code/binary into to create a new deployment image.
An easy way to think about S2i builder images is that it is analogous to Buildpacks in which they set the environment for applications.
Directory Structure
S2i builder images have the following directory structure:
/
/s2i/
/s2i/assemble
/s2i/usage
/s2i/run
Dockerfile
Key details to note is that when you create a new build that uses an s2i builder image as its base layer, your source code will be injected into /tmp/src
of the builder image. You will need to keep this in mind when you write your assemble
scripts.
S2i Builder Image Default Files
/s2i/assemble
This is a bash script that contains instructions that will be run right after your deploying app source code is injected into /tmp/src
of the S2i builder image.
#!/bin/sh
set -ex
echo "---> Preparing source..."
mkdir -p /tmp/myapp
cp -Rf /tmp/src/src/. /tmp/myapp
/s2i/usage
This script is run when the builder image is run w/o any additional commands. Its sole responsibility is to print out the usage of the builder image in text form.
/s2i/run
This script is run during runtime when the derived application image runs. Should contain the actual running of a long-lived process.
#!/bin/sh
set -e
echo "Running myapp..."
cat /tmp/myapp/*
echo Sleeping...
while true; do sleep 1; echo -n .;done
S2i Builder Image Dockerfile
A typical Dockerfile should contain at minimum the following steps:
# This image creates a very simple s2i builder image
# We are basing our builder image on openshift base-centos7 image
FROM openshift/base-centos7
# Set labels used in OpenShift to describe the builder images
LABEL io.k8s.description="simple s2i builder example" \
io.k8s.display-name="simple s2i builder example" \
io.openshift.s2i.scripts-url="image:///usr/libexec/s2i" \
io.openshift.tags="builder"
# Copy the example S2I scripts to the expected location
COPY ./s2i/ /usr/libexec/s2i
# Set the default user for the image
USER 1001
# Set the default CMD to print the usage of the image, if somebody does docker run
CMD /usr/libexec/s2i/usage
Bonus: The
io.openshift.s2i
annotations can provide you with more configurable settings to help you with your s2i image creation. For example, you can useio.openshift.s2i.destination="/path/where/appcode/is/injected"
. If not your application code will be injected into/tmp/src
of the base image.
Cheat Code
To quickly generate the necessary files to get your S2i builder image started (including the above directory structure), you can actually cheap by using the s2i
cli. You can grab it at http://github.com/openshift/source-to-image
$ s2i create <image name> <relative path to name of directory to use to contain the files>
Deploying your Builder Image onto Openshift
oc new-build --name <name of builder image> --binary=true # Create the build configuration (using Docker build strategy)
oc start-build <name of builder image> --from-dir=. # Start the build, using the current directory
oc logs bc/<name of builder image> -f # Check the build output for errors
When this is complete, this creates an image called <name of builder image>
into Openshift which you can then use as the source base image.
Deploying your App onto Openshift
Now that you have your app, all you really need is to send an instruction to have your app baked into your builder image and return an output image which youc an then use to deploy.
In the directory of your app source code, create a new build configuration
. Like the steps above, oc new build
creates a build instruction to tell what is the expected output image.
$ oc new-build --binary=true -i <name of builder image> --name <name of output image/appname>
binary=true just instructs Openshift to expect the incoming files to be from a tarball/raw files
At this stage, you should have a working build configuration. Now let’s start to build an output image. The following command will push all the files in the current directory up start a build.
# make sure you're in your app source code directory
$ oc start-build <name of output image/appname> --from-dir=.
$ oc logs bc/<name of output image> -f
After this is completed, just do an oc new-app <name of output image/appname>
and your app is deployed!
Bonus: If you want your application to overwrite any of the
assemble/run/usage
scripts in your builder image, you can add them in.s2i/bin/
of yourapplication root
. The S2i process will find these file and inject them into the builder image during build time.