00 - Cloud-Native App Dev development

Cloud Native AppDev without Tears – Using odo to Boost your Workflow

Traditionally application development and deployment across environments has been very tedious and error prone. For example in the Java world you would work with different packaging formats such as ears, wars and jars each with environment specific configuration usually dispersed all over the place. Then your app might behave differently on each operating system due to some native dependencies. No wonder application updates were a thing to avoid rather than to embrace.

Challenges of Containerized Apps

One of the many benefits that containerization brings is that we finally have a cross-platform, programming language agnostic packaging format ( OCI-Image ) that encapsulates code, configuration as well as operating system dependencies. Your application will actually run the same on your laptop as well as on your production servers. No more ‘works on my machine’ excuses.

To run your images at scale you will want to rely on the Kubernetes scheduler as the industry standard. To run them in production you will need a fully integrated and secure container platform such as OpenShift.

Working with well defined and immutable images is great from a DevOps perspective as any version and deployment can be traced to a defined code state. But there are times in the development cycle of an engineer where small iterative code changes need to be tested to try out a new feature or to debug an error. There may be some dependencies to the platform where our images are run, in terms of Kubernetes resources, databases or other applications. So testing the app only in your local development environment is not sufficient. On the other hand you do not want to do a full image build for every small code change to save time and resources.

Also being a developer and just coming to the world of Kubernetes can be a bit daunting. Maybe you just want to focus on writing great code and not having to learn all about Kubernetes deployments.

Introducing odo 2.x

Well, we have got you covered: There is a command line tool called odo for that. odo or ‘OpenShift Do’ has just switched to its major release version 2.x in all it’s OpenSource goodness. It addresses the so called ‘inner loop’ of cloud native development. A dev wants to quickly develop a multi-component application on OpenShift and keep pushing updates into the app without having to worry about Kubernetes specifics or permanently rebuilding images. It is all about ‘staying in the flow’.

As of version 2.x odo also supports plain Kubernetes but you will need some additional steps to make up for missing components such as OpenShift Routes.

How do I get started you ask?

Easy as that: Download the latest version of odo for your operating system and add it to your path. At the time of writing this was 2.0.5. Here are more detailed instructions if required.

So let’s see what capabilities we have just acquired.

On a terminal enter:

$ odo catalog list components Odo Devfile Components: NAME DESCRIPTION REGISTRY java-maven Upstream Maven and OpenJDK 11 DefaultDevfileRegistry java-openliberty Open Liberty microservice in Java DefaultDevfileRegistry java-quarkus Upstream Quarkus with Java+GraalVM DefaultDevfileRegistry java-springboot Spring Boot® using Java DefaultDevfileRegistry java-vertx Upstream Vert.x using Java DefaultDevfileRegistry java-wildfly Upstream WildFly DefaultDevfileRegistry java-wildfly-bootable-jar Java stack with WildFly in bootable Jar mode, OpenJDK 11 and... DefaultDevfileRegistry nodejs Stack with NodeJS 12 DefaultDevfileRegistry python Python Stack with Python 3.7 DefaultDevfileRegistry python-django Python3.7 with Django DefaultDevfileRegistry Odo S2I Components: NAME PROJECT TAGS SUPPORTED java openshift latest,openjdk-11-el7,openjdk-11-ubi8,openjdk-8-el7 YES nodejs openshift 10-SCL,12-ubi8,latest YES dotnet openshift 2.1-el7,2.1-ubi8,2.2,3.0,3.1-el7,3.1-ubi8,latest NO golang openshift 1.11.5,1.13.4-ubi7,1.13.4-ubi8,latest NO httpd openshift 2.4-el7,2.4-el8,latest NO java openshift openjdk-8-ubi8 NO modern-webapp openshift 10.x,latest NO nginx openshift 1.10,1.12,1.14,1.14-el8,1.16-el7,1.16-el8,latest NO nodejs openshift 10-ubi7,10-ubi8,12-ubi7,8,8-RHOAR NO perl openshift 5.24,5.26-el7,5.26-ubi8,5.30-el7,latest NO
Code language: JavaScript (javascript)

Well those are quite some runtimes to build interesting polyglot microservices. You will notice the categories S2I and Devfile.

  • S2I – the classic way of building images in odo 1.x which still works fine
  • Devfiles – a new feature since version 2.x that opens some interesting new possibilities. For one thing Devfiles are the base definition for CodeReady Workspaces and Eclipse Che. So you could share and jointly work on this environment in a standard browser. Also devfiles make it easier to support and define new languages and runtimes.

Prerequisite : Container Platform

Since we will be deploying to OpenShift you will need to have access to a cluster. If you don’t yet have an OpenShift running there are lots of free options to get started quickly. Either choose one of the many options from or give the new developer sandbox a try.

If you do not yet have the main OpenShift cli oc installed login to the OpenShift webconsole and on the top right click on the questionmark icon and the ‘Command Line Tools’ to download oc for your system. As a fun fact did you spot the odo cli there as well?

Now establish an authenticated connection to the cluster that odo can use. On the same top right menu, click on your username and then ‘Copy Login Command ‘.

You may have to authenticate again and then click on ‘Display Token’. This will give you a full login command with a temporary token. Paste this command into your console and the connection is established.

Your first app

To get your first app running we will be using a built-in sample project. Let’s create a new project called ‘odo’ and a new NodeJS app:

$ odo project create odo $ odo create nodejs --starter Devfile Object Validation ✓ Checking devfile existence [124412ns] ✓ Creating a devfile component from registry: DefaultDevfileRegistry [136069ns] Validation ✓ Validating if devfile name is correct [192694ns] Starter Project ✓ Downloading starter project nodejs-starter from [430ms] Please use `odo push` command to create the component with source deployed
Code language: JavaScript (javascript)

A devfile has been created with default values derived from your input and the chosen runtime. All that is left to do is push the code to OpenShift.

$ odo push alidation ✓ Validating the devfile [98840ns] Creating Kubernetes resources for component nodejs ✓ Waiting for component to start [6s] ✓ Waiting for component to start [34ms] Applying URL changes ✓ URL http-3000: created Syncing to component nodejs ✓ Checking files for pushing [7ms] ✓ Syncing files to the component [715ms] Executing devfile commands for component nodejs ✓ Waiting for component to start [18ms] ✓ Executing install command "npm install" [4s] ✓ Executing run command "npm start" [1s] Pushing devfile component nodejs ✓ Changes successfully pushed to component
Code language: JavaScript (javascript)

This will create and deploy the pod with the container, containing your NodeJS application and will also create a route to access it. All with one command.

Now go to your OpenShift webconsole and in the menu at the top left switch to ‘Developer’ perspective. Within the project drop down menu at the top select the ‘odo’ project that we created and you will see you app running.

Click on the ‘Open URL’ icon and a new browser tab will display greeting you with your NodeJS webservice endpoint:

‘Hello from Node.js Starter Application!’

Now lets fire up an inner loop update. In the local folder open the file server.js, look for the endpoint code and change the response by adding the word ‘ODO’ to the response.

... app.get('/', (req, res) => { // Use req.log (a `pino` instance) to log JSON:{message: 'Hello from Node.js Starter Application!'}); res.send('Hello from Node.js ODO Starter Application!'); }); ....
Code language: PHP (php)

Push the code again :

$ odo push

Have a look back at the ‘Developer’ perspective in OpenShift: No new image was created. No redeployment took place. And if you call your endpoint now you should already see your new greeting.

That’s already pretty neat but we can take this up one more level. How about live reload to a remote container platform?

Just tell odo to watch your code for changes:

$ odo watch

Now change your server.js file again. How about a reply like this?

... app.get('/', (req, res) => { // Use req.log (a `pino` instance) to log JSON:{message: 'Hello from Node.js Starter Application!'}); res.send('Hello from Node.js ODO Watch Starter Application!'); }); ....
Code language: PHP (php)

Save the file and see odo immediately push your changes to your pod on OpenShift. Reload the browser tab pointing to the endpoint of your app to see the changes. Now you can work as if everything was running on your local system.

Remote Debugging

But what if you encountered some issues that only appear on the remote pod? Well odo is here to help with the debug command.

The sample NodeJS project is already set up for debugging, all you have to do is launch the app in debug mode, set up a local port forwarding and then connect with your favorite IDE. Let’s take it step by step.

Push again with the debug option and forwarding local port 5858 to remote port 5858:

$ odo push --debug $ odo debug port-forward

In a second terminal in the same folder you can check if the local port is open:

$ odo debug info Debug is running for the component on the local port : 5858

As an example I will set up remote debugging in VSCodium. This should work the same in VSCode. For others IDEs check the guides on how to set up remote debugging.

Open the project in the IDE:

$ codium .

Then click on the debug icon on the left (1) and the add a new configuration with the dropdown menu at the top (2).

Now you can open launch.json for editing.

Set a new remote debug configuration:

{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: "version": "0.2.0", "configurations": [ { "type": "node", "request": "attach", "name": "Attach to remote", "address": "", "port": 5858 } ] }
Code language: JSON / JSON with Comments (json)

Click ‘Attach to remote’ in the previous drop down menu.

You should see ‘App started on PORT 3000’ in the IDE terminal.

Now open the server.js in the IDE editor and set a breakpoint at the line where the endpoint is called by clicking on the line number. A red dot will appear.

Call the endpoint of the app again by reloading your browser pointing to the NodeJS app endpoint. The app will now stop at that line and and you can inspect all the variables as if running locally.


We have seen how odo can help to quickly get started with cloud native application development without having to become a Kubernetes expert. As a developer we can work with the same IDE and the same local workflow that we are used to, while deploying the apps to OpenShift with just one command or even fully automatic. That is the power of the ‘inner loop’ for containerized development.

odo has a lot more to offer. For example you may want to look at setting up persistent storage for your apps next. Have a look at the official odo website to learn more and launch your first app into the world of containers.

By Daniel Brintzinger

Daniel Brintzinger is a Senior Solution Architect at Red Hat living in Berlin. He has been working as Developer, Consultant and Software Architect with focus on Service, Integration and Cloud Architectures. Daniel is passionate about Open Source, not just from a technological perspective but also as a cultural shift in the way we work and deliver greatness together.

One reply on “Cloud Native AppDev without Tears – Using odo to Boost your Workflow”