Binary Builds
Introduction
The binary build feature in OpenShift allows developers to upload source or artifacts directly to a build instead of having the build pull source from a Git repository URL. Any BuildConfig with a strategy of source, Docker, or custom may be started as a binary build. When starting a build from local artifacts, the existing source reference is replaced with the source coming from the local user’s machine.
The source may be supplied in several ways which correspond to arguments available when using the start-build command:
From a file (
--from-file
): This is the case when the entire source of the build consists of a single file. For example, it may be aDockerfile
for a Docker build,pom.xml
for a Wildfly build, orGemfile
for a Ruby build.From a directory (
--from-directory
): Use this when the source is in a local directory and is not committed to a Git repository. Thestart-build
command will create an archive of the given directory and upload it to the builder as source.From an archive (
--from-archive
): Use this when an archive with the source already exists. The archive may be in eithertar
,tar.gz
, orzip
format.From a Git repository (
--from-repo
): This is for source that is currently part of a Git repository on the user’s local machine. The HEAD commit of the current repository will be archived and sent to OpenShift for building.
Use Cases
Binary builds remove the requirement for a build to pull source from an existing Git repository. Reasons to use binary builds include:
Building and testing local code changes. Source from a public repository can be cloned and local changes can be uploaded to OpenShift for building. Local changes do not have to be committed or pushed anywhere.
Building private code. New builds can be started from scratch as binary builds. The source can then be uploaded directly from your local workstation to OpenShift without having to check it in to an SCM.
Building images with artifacts from other sources. With Jenkins pipelines, binary builds are useful to combine artifacts built with tools such as Maven or C compiler, and runtime images that make use of those builds.
Limitations
Binary builds are not repeatable. Because binary builds rely on the user uploading artifacts at build start, OpenShift cannot repeat the same build without the user repeating the same upload every time.
Binary builds cannot be triggered automatically. They can only be started manually when the user uploads the required binary artifacts.
Builds that are started as binary builds may also have a configured source URL. If that’s the case, triggers will successfully launch the build but source will come from the configured source URL and not from what was supplied by the user the last time the build ran. |
Tutorials Overview
The following tutorials assume that you have an OpenShift cluster available and that you have a project where you can create artifacts. It requires that you have both git
and oc
available locally.
Tutorial: Building local code changes
Create a new application based on an existing source repository and create a route for it:
$ oc new-app https://github.com/openshift/ruby-hello-world.git
$ oc expose svc/ruby-hello-world
Wait for the initial build to complete and view the application’s page by navigating to the route’s host. You should get a welcome page:
$ oc get route ruby-hello-world
Clone the repository locally:
$ git clone https://github.com/openshift/ruby-hello-world.git
$ cd ruby-hello-world
Make a change to the application’s view. Using your favorite editor, edit
views/main.rb
: Change the<body>
tag to<body style="background-color:blue">
.Start a new build with your locally-modified source. From the repository’s local directory, run:
----
$ oc start-build ruby-hello-world --from-dir="." --follow
----
Once your build has completed and the application has redeployed, navigating to the application’s route host should result in a page with a blue background.
You can keep making changes locally and building your code with oc start-build --from-dir
.
You can also create a branch of the code, commit your changes locally, and use the repository’s HEAD as the source for your build:
$ git checkout -b my_branch
$ git add .
$ git commit -m "My changes"
$ oc start-build ruby-hello-world --from-repo="." --follow
Tutorial: Building private code
Create a local directory to hold your code:
$ mkdir myapp
$ cd myapp
In the directory create a file named
Dockerfile
with the following content:FROM centos:centos7
EXPOSE 8080
COPY index.html /var/run/web/index.html
CMD cd /var/run/web && python -m SimpleHTTPServer 8080
Create a file named
index.html
with the following content:<html>
<head>
<title>My local app</title>
</head>
<body>
<h1>Hello World</h1>
<p>This is my local application</p>
</body>
</html>
Create a new build for your application:
$ oc new-build --strategy docker --binary --docker-image centos:centos7 --name myapp
Start a binary build using the local directory’s content:
$ oc start-build myapp --from-dir . --follow
Deploy the application using
new-app
, then create a route for it:$ oc new-app myapp
$ oc expose svc/myapp
Get the host name for your route and navigate to it:
$ oc get route myapp
After having built and deployed your code, you can iterate by making changes to your local files and starting new builds by invoking oc start-build myapp --from-dir
. Once built, the code will be automatically deployed and the changes will be reflected in your browser when you refresh the page.
Tutorial: Binary artifacts from pipeline
Jenkins on OpenShift allows using slave images with the appropriate tools to build your code. For example, you can use the maven
slave to build a WAR from your code repository. However, once this artifact is built, you need to commit it to an image that contains the right runtime artifacts to run your code. A binary build may be used to add these artifacts to your runtime image. In the following tutorial, we’ll create a Jenkins pipeline that makes use of the maven
slave to build a WAR, and then uses a binary build with a Dockerfile
to add that WAR to a wildfly runtime image.
Create a new directory for your application:
$ mkdir mavenapp
$ cd mavenapp
Create a
Dockerfile
that copies a WAR to the appropriate location inside a wildfly image for execution. Copy the following to a local file namedDockerfile
:FROM wildfly:latest
COPY ROOT.war /wildfly/standalone/deployments/ROOT.war
CMD $STI_SCRIPTS_PATH/run
Create a new BuildConfig for that Dockerfile:
This will automatically start a build that will initially fail because the
ROOT.war
artifact is not yet available. The pipeline below will pass that WAR to the build using a binary build.$ cat Dockerfile | oc new-build -D - --name mavenapp
Create a BuildConfig with the Jenkins pipeline that will build a WAR and then use that WAR to build an image using the previously created
Dockerfile
. The same pattern can be used for other platforms where a binary artifact is built by a set of tools and is then combined with a different runtime image for the final package. Save the following code tomavenapp-pipeline.yml
:apiVersion: v1
kind: BuildConfig
metadata:
name: mavenapp-pipeline
spec:
strategy:
jenkinsPipelineStrategy:
jenkinsfile: |-
pipeline {
agent { label "maven" }
stages {
stage("Clone Source") {
steps {
checkout([$class: 'GitSCM',
branches: [[name: '*/master']],
extensions: [
[$class: 'RelativeTargetDirectory', relativeTargetDir: 'mavenapp']
],
userRemoteConfigs: [[url: 'https://github.com/openshift/openshift-jee-sample.git']]
])
}
}
stage("Build WAR") {
steps {
dir('mavenapp') {
sh 'mvn clean package -Popenshift'
}
}
}
stage("Build Image") {
steps {
dir('mavenapp/target') {
sh 'oc start-build mavenapp --from-dir . --follow'
}
}
}
}
}
type: JenkinsPipeline
triggers: []
Create the pipeline build. If Jenkins is not deployed to your project, creating the BuildConfig with the pipeline will result in Jenkins getting deployed. It may take a couple of minutes before Jenkins is ready to build your pipeline. You can check the status of the Jenkins rollout by invoking,
oc rollout status dc/jenkins
:$ oc create -f ./mavenapp-pipeline.yml
Once Jenkins is ready, start the pipeline defined previously:
$ oc start-build mavenapp-pipeline
When the pipeline has finished building, deploy the new application using new-app and expose its route:
$ oc new-app mavenapp
$ oc expose svc/mavenapp
Using your browser, navigate to the route for the application:
$ oc get route mavenapp