Red Hat OpenShift includes tooling for building your applications.
A build process uses input parameters and source code or application binaries to create container images.
The BuildConfig resource contains the definition for the build process, which includes:
A build trigger that starts the build process.
A build strategy that defines how the build process works.
One or more input sources, such as git, binary, or inline definitions.
The build process output, which most often is a runnable container image.
On every build execution, OpenShift creates a Build object for that particular run.
The Build object contains metadata and the build execution logs.
The following are the available build strategies in OpenShift:
The resulting build object is a runnable image in the case of S2I or Docker strategies.
Custom builds can have any type of output, such as RPMs or base images.
Source-to-Image (S2I) Build
This strategy enables developers to build container images without manually creating a Containerfile.
The S2I strategy creates a new container image by using the application source code.
OpenShift clones the application source code into a builder image that is capable of building it.
Then, the S2I process creates a container image that you can deploy to the cluster.
The docker build strategy uses the buildah CLI to build a new container image by running the instructions from an existing Containerfile.
The docker strategy can retrieve the Containerfile and the artifacts to build the container image from a Git repository, or can use a Containerfile provided inline in the build configuration as a build input source.
Developers do not need to set up the container tooling on their workstation because the build runs as a pod inside the OpenShift cluster.
The custom build strategy specifies a builder image responsible for the build, which enables developers to define the build process.
Custom builds require a high level of cluster privileges to run.
See the references section of this unit to find more information about how to create a custom builder image.
OpenShift generates a BuildConfig when you create an application by either running the oc new-app command or by using the web console.
You can edit the BuildConfig definition to customize it to your needs.
The following example builds a PHP application by using the source strategy and a git input source:
kind: BuildConfig
apiVersion: build.openshift.io/v1
metadata:
name: "php-sample-build"
spec:
runPolicy: "Serial"
triggers:
- type: "ImageChange"
source:
git:
uri: "http://services.lab.example.com/php-helloworld"
strategy:
sourceStrategy:
from:
kind: "ImageStreamTag"
name: "ruby-20-centos7:latest"
output:
to:
kind: "ImageStreamTag"
name: "origin-ruby-sample:latest"
| The runPolicy attribute defines whether several builds can run simultaneously.
The Serial value represents that only one build can run at a time. |
| The ImageChange trigger that creates a new build when the ruby-20-centos7:latest image stream changes. |
| The Git source attribute responsible for defining the input source of the build.
A BuildConfig can have multiple inputs. |
| Defines the Source build strategy, which uses the S2I technology to build the container image. |
| The output attribute defines where to push the new container image after a successful build. |
| Output image kind set to ImageStreamTag, which targets the image creation to the image registry integrated in OpenShift.
To specify any image registry, use the DockerImage kind, which allows full qualified image names. |
Build inputs provide source content for builds.
OpenShift supports the following types of input sources, listed in order of precedence:
Inline Dockerfile: Specifies the Containerfile instructions to build an image.
Image: Enables injecting sources from container images.
The image source can be a container image or an image stream.
Git: OpenShift clones the input application source code from a Git repository.
The source code location inside the repository is configurable.
Binary: Enables uploading binary content from a local file system to the builder.
Input secrets: You can use input secrets to enable creating credentials for the build that are not available in the final application image.
External artifacts: Allow copying binary files to the build process.
You can combine multiple inputs in a single build.
However, as the inline Containerfile takes precedence, it overrides any other Containerfile provided by another input.
Additionally, binary input and Git repositories are mutually exclusive inputs.
Note
Although OpenShift offers many strategies and input sources, the most common scenarios are using either the Source or Docker strategies, with a Git repository as the input source.
Using Sensitive Information in Builds
Builds might require sensitive information, such as credentials, tokens, or certificates, to access the build dependencies.
Build input data can persist in the resulting container image or show in the build logs.
To prevent sensitive information from appearing in the output image, store the sensitive data in Kubernetes secrets and configuration maps.
Then, you can configure the build configuration source property to make this information available during the build process.
The following example shows how to safely provide an S2I build for a Java application with access information to download external dependencies:
...
source:
git:
uri: "http://services.lab.example.com/java-helloworld"
configMaps:
- configMap:
name: settings-mvn
destinationDir: ".m2"
secrets:
- secret:
name: secret-mvn
destinationDir: ".ssh"
| Configuration map that contains the settings.xml file and mounts it to the build container .m2 directory. |
| Secret that mounts the ssh key to the build container .ssh directory. |
When using the Docker strategy, use build volumes to mount the secrets and configuration maps in a secure way.
This type of volume is not included in the final container image.
The following example shows how to safely provide access information to download dependencies for the Docker strategy and the Java programming language:
spec:
dockerStrategy:
volumes:
- name: settings-mvn
mounts:
- destinationPath: /opt/app-root/src/.m2
source:
type: ConfigMap
configMap:
name: my-config
- name: secret-mvn
mounts:
- destinationPath: /opt/app-root/src/.ssh
source:
type: Secret
secret:
secretName: my-secret
| Build volume with a configuration map that contains the settings.xml and mounts it to the /opt/app-root/src/.m2 directory. |
| Build volume with a secret that contains the ssh key and mounts it to the /opt/app-root/src/.ssh directory. |
Source-to-Image (S2I) Language Detection
The simpler syntax for the oc new-app command requires only the Git repository URL as an argument, and then OpenShift tries to auto-detect the programming language used by the application and select a compatible builder image.
The programming language detection feature relies on finding specific file names at the root of the Git repository.
The following table displays some common options, but it is not an extensive list of source-to-image compatible languages:
Refer to the OpenShift product documentation for the complete compatible languages list.
The oc new-app command can use a range of command-line options to force a particular choice, which were presented earlier in this course.
OpenShift follows a multistep algorithm to determine if the URL points to a source code repository and if so which builder image should perform the build.
The following is a simplified description of the S2I process:
If the URL points to a Git repository, then OpenShift retrieves a file list from the repository and searches for a Dockerfile file.
If found, the build configuration uses a docker strategy.
Otherwise, the build configuration uses a source strategy, which needs an S2I builder image.
OpenShift searches for image streams that match the language builder name as the value of the supports annotation.
The first match becomes the S2I builder image.
If no annotation matches, then OpenShift searches for an image stream whose name matches the language builder name.
The first match becomes the S2I builder image.
Steps 2 and 3 make it easy to add new builder images to an OpenShift cluster.
It also means that multiple builder images can be potential matches.
To force the use of a certain image stream, you can use the -i option for a PHP 7.3 application:
[user@host ~]$ oc new-app -i php:7.3 \
https://github.com/RedHatTraining/DO288-apps/php-helloworld
This requires a local Git client because the oc new-app command first clones the repository to do the build strategy detection.
If the build strategy detection results in the source build strategy, then the cluster looks for an image stream named php with the 7.3 version to invoke the builder.
To skip the build strategy detection, you can use the following tilde (~) syntax:
[user@host ~]$ oc new-app \
php:7.3~https://github.com/RedHatTraining/DO288-apps/php-helloworld
The Source-to-Image (S2I) Build Process
The S2I build process involves the following components:
- Application source code
This is the source code for the application.
- S2I scripts
The S2I build process relies on executing the S2I scripts at various stages of the build workflow.
The scripts, and a brief description of what they do, are listed in the following table:
The S2I build process is as follows:
OpenShift instantiates a container based on the S2I builder image, and creates a tar file containing the source code and the S2I scripts.
OpenShift then streams the tar file into the container.
Before running the assemble script, OpenShift extracts the tar file from the previous step, and saves the contents into the location specified by either the --destination option or by the io.openshift.s2i.destination label from the builder image.
The default location is the /tmp directory.
If this is an incremental build, then the assemble script restores the build artifacts previously saved in a tar file by the save-artifacts script.
The assemble script builds the application from source and places the binaries into the appropriate directories.
If this is an incremental build, the save-artifacts script is executed and saves all dependency build artifacts to a tar file.
After the assemble script completes, OpenShift commits the container and sets the run script as the CMD instruction for the final image.
Creating an S2I Builder Image
To create a builder image, declare a Dockerfile file with the tools that you need to build the application, such as compilers, build tools, and the script files mentioned previously.
The following Dockerfile builder file defines an NGINX server builder:
FROM registry.access.redhat.com/ubi8/ubi:8.0
LABEL io.k8s.description="My custom Builder" \
io.k8s.display-name="Nginx 1.6.3" \
io.openshift.expose-services="8080:http" \
io.openshift.tags="builder,webserver,html,nginx" \
io.openshift.s2i.scripts-url="image:///usr/libexec/s2i"
RUN yum install -y epel-release && \
yum install -y --nodocs nginx && \
yum clean all
EXPOSE 8080
COPY ./s2i/bin/ /usr/libexec/s2i
| Set the labels that OpenShift uses to describe the builder image. |
| Set the path for the S2I mandatory scripts (run, assemble). |
| Install the NGINX web server package and clean the Yum cache. |
| Set the default port for applications built using this image. |
| Copy the S2I scripts to the /usr/libexec/s2i directory. |
You can define the assemble script as follows:
#!/bin/bash -e
if [ "$(ls -A /tmp/src)" ]; then
mv /tmp/src/* /usr/share/nginx/html/
fi
| Override the default NGINX index.html file. |
You can define the run script as follows:
#!/bin/bash -e
/usr/sbin/nginx -g "daemon off;"
| Prevent the NGINX process from running as a daemon so that the container does not exit after the process runs the exec script. |
Overriding S2I Builder Scripts
S2I builder images provide default S2I scripts.
You can override the default S2I scripts to define how your application is built and executed without creating a S2I builder image.
To do this, include your S2I scripts in the source code repository for your application in the .s2i/bin directory.
When OpenShift starts the S2I process, it inspects the source code directory, the custom S2I scripts, and the application source code.
OpenShift includes these files in the tar file injected into the S2I builder image.
OpenShift then executes any custom scripts if they exist or the S2I builder image scripts otherwise.