Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

4 Ways to Build Applications in OpenShift

DZone 's Guide to

4 Ways to Build Applications in OpenShift

Want to learn more about building applications with OpenShift? Check out this post on four different ways to build software and automate builds with OpenShift.

· Cloud Zone ·
Free Resource

We are going to discuss the different strategies for building our software in OpenShift. These strategies are useful if you need to solve any of the following problems:

  • Learn how to build your software
  • You want to automate your builds
  • Build existing applications
  • You want to run legacy applications inside containers on the cloud

You can run these examples in a local instance of OpenShift or a Virtual Machine. Also, if you don't want to install it locally, you can get free access to OpenShift.io

Build Configuration

Creating your own images requires some non-trivial knowledge about Linux systems setup. For this reason, OpenShift includes a set of images known as image builders. These images implement an opinionated way to build software that we can leverage to focus less in the configuration and more on the application development.

To check the images available to build our software, check out the following code:

oc get is -n openshift | awk '{ print $1 }'

# from Openshift.IO. 
NAME
apicast-gateway
dotnet
dotnet-runtime
httpd
java
jboss-webserver30-tomcat7-openshift
jboss-webserver30-tomcat8-openshift
jboss-webserver31-tomcat7-openshift
jboss-webserver31-tomcat8-openshift
jenkins
mariadb
mongodb
mysql
nodejs
perl
php
postgresql
python
redhat-openjdk18-openshift
redhat-sso72-openshift
redis
rhdm70-decisioncentral-openshift
rhdm70-kieserver-openshift
ruby
wildfly


By the images name, we can infer what type of programming language or framework they support, so let's pick one of these images and build something. 

Building Your Applications From Source Code

This is the best way to get started with OpenShift, because it requires very little setup, and as long as you follow the guidelines of the builder image, your work is reduced to just passing a git repository URL.

oc new-build <builder-image>~<git-repository> --name=<optional>


Here is an example of building a Node.js application:

oc new-build nodejs~https://github.com/cesarvr/hello-world-nodejs --name-nodejs-build


This particular build (Node.js builder) has two stages: cloning your code from the git repository and resolve the dependencies using npm (this is a Node.JS package manager similar to Maven). When the project is ready to run, a snapshot is taken and is stored in the registry.

If we are able to restore this image to its previous state (project ready to run), then we can deploy this application with a high degree of confidence. That's the magic behind containers.

We can find the stored image by running the following command: 

oc get is

#NAME                DOCKER REPO
 nodejs-build        docker-registry.default.svc:5000/hello01/nodejs-build


Review: 

  •  Pros: Less complexity, easy for starters, and good for a greenfield project.

  • Cons: Your code needs to be compatible with the build framework implemented by the image builder. 

Build an Application From Existing Binary

Sometimes, we won't be able to use the source to image approach, because we are previously generating the binary using a build automation service, or we are using a non-supported build framework. In this situation, we can still use the builder images for runtime.

In these cases, we can configure the build to receive a binary instead of source code. Let’s take this Spring Boot application. For example, I’ve created it using this getting started guide, and we are going to use Gradle, which is not supported, to demonstrate how to configure this type of build.

First, you will need to clone this repository: 

git clone https://github.com/cesarvr/Spring-Boot spring_boot

# enter the folder
cd spring_boot


Now, we need to generate an executable  .jar:

#Generate the binary executable file in ./builds/libs/
gradle bootJar 

#We got a file named: hello-boot-0.1.0.jar


Now that we got the jar file, we need to choose the proper image builder to handle this binary. We are going to choose the java image. This image expects an executable jar file to run. 

#Generate the build configuration
oc new-build java --name=java-binary-build --binary=true


The last step is to trigger the build:

oc start-build bc/java-binary-build \
--from-file=./build/libs/hello-boot-0.1.0.jar \
--follow


Review: 

  •  Pros: Offers a convenient way to integrate with automation servers and unsupported build technology.

  • Cons: The binary needs to be compatible with the runtime. 

Creating Your Own Container

If you want to migrate applications, which runtime is not supported by any image builder (JDK1.4, COBOL, etc.), then you have to provide a runtime for this application to run, as long as the runtimes don't have any deprecated system calls. In which case, they will be easier to patch than trying to rewrite the whole stuff. 

To provide this alternative runtime, you need to define your own container as part of the build configuration. To illustrate this point, we are going to create a minimal image to run our Node.js application above.

First, let's clone our application.

# clone the app
git clone https://github.com/cesarvr/hello-world-nodejs hellojs

cd hellojs


Once we are there, we create a build. Dockerfile

FROM mhart/alpine-node:base-8
COPY * /run/


First, we defined a base image to start our image from inside alpine-node and its a folder called run. We are going to copy the content of our project there. 

EXPOSE 8080
CMD ["node", "/run/app.js"]


Then, we set up the container to expose the port 8080 (that's the port we are using to accept traffic). Finally, we run the node against our script. 

To create the build configuration: 

 cat build.Dockerfile | oc new-build --name node-container --dockerfile='-'


We create the build by using the new-build command,  but this time, we aren't going to define a builder image to use, instead, we are going to use the --dockerfile  parameter. The --dockerfile accepts a string containing Dockerfile instructions. If we pass a dash  --dockerfile='- ‘ , we can stream the contents of our build.Dockerfile.

Also, the Dockerfile instructions are executed from the folder that we are making the call. This means that making the call from another folder can have undesired effects.

To trigger this build:

oc start-build bc/node-container --follow


Review: 

  • Pros: Very flexible because you can define your own runtime. 

  • Cons: Complex and difficult to maintain. 

Docker strategy is disabled in Openshift.io, but you can still practice using  oc cluster up or  minishift.

Exporting Images 

This one does not use a BuildConfig, but I just included it because it is another option and can be useful in desperate circumstances. If you are creating your own images and pushing it to an external registry, you can still deploy this image in Openshift. 

Importing an image inside your cluster is easy:

oc import-image microservice:latest \ 
  --from=your-docker-registry.io/project-name/cutting-edge:latest \
  --confirm


To check your image, you just need to write this command:

oc get is

Name                   Docker Repo                                 
microservice   your-docker-registry.io/hello01/cutting-edge:latest 


When to use this? You can use this when you have legacy applications running in containers and they are stored in an external registry, like Nexus.

Deploying Your Application

We have our images; what do we do next? Deploying an image is easy; let see how to do this. First, we need to choose the image we want to deploy. 

oc get is

NAME                DOCKER REPO                                                               
java-binary-build   docker-registry.default.svc:5000/hello01/java-binary-build   
node-build          docker-registry.default.svc:5000/hello01/node-build          


This command locates the images we have created so far (these are images sources are created automatically with every build configuration definition). The next step is to create an OpenShift application by choosing any of the images. I would use the  java-binary-build.

To create these components:

oc new-app java-binary-build --name=java-ms


Once this command finishes, our application should be deployed and running, but it won't be able to receive traffic. For that, we need to expose our application:

# Expose the service of our application
oc expose svc java-ms

# Now we want to know the URL. 
oc get route

NAME        HOST/PORT                                                   
java-ms     java-ms-hello01.7e14.starter-us-west-2.openshiftapps.com

# URL for the exterior ^^


Our application should be available to receive traffic.

curl java-microservice-hello01.7e14.starter-us-west-2.openshiftapps.com
#Greetings from Spring Boot!
Topics:
cloud ,openshift container platform ,nodejs

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}