Hosting your SBT-built Java project on RedHat’s OpenShift platform

If you’re more of an OpenShift than Heroku fan, here’s how you can get your SBT-built Java project onto OpenShift. OpenShift has fewer dynos (“gears”) at the free tier (only 3) but they idle after 24 hours instead of 1, and you get 1gb of disk storage to play with. They’ve also got a wide number of supported technologies you can run, be they languages, databases or servers. And “You could do OpenShift now and Docker will be our container tech in the new release this year” says @TheSteve0.


You’ll need a DIY cartridge, and an SBT-built Java project which uses the SBT native packager (like this one here).

OpenShift uses a set of action hooks to control what happens when you perform a Git Push. The problem is that SBT uses directories all over the filesystem and you’ll end up with the following errors when pushing a normal SBT project.

remote: Building git ref 'master', commit d66a2bd
remote: java.io.IOException: No such file or directory
remote: 	at java.io.UnixFileSystem.createFileExclusively(Native Method)
remote: 	at java.io.File.createNewFile(File.java:1006)
remote: 	at xsbt.boot.Locks$.apply0(Locks.scala:34)
remote: 	at xsbt.boot.Locks$.apply(Locks.scala:28)
remote: 	at xsbt.boot.Launch.locked(Launch.scala:238)
remote: 	at xsbt.boot.Launch.app(Launch.scala:147)
remote: 	at xsbt.boot.Launch.app(Launch.scala:145)
remote: 	at xsbt.boot.Launch$.run(Launch.scala:102)
remote: 	at xsbt.boot.Launch$$anonfun$apply$1.apply(Launch.scala:35)
remote: 	at xsbt.boot.Launch$.launch(Launch.scala:117)
remote: 	at xsbt.boot.Launch$.apply(Launch.scala:18)
remote: 	at xsbt.boot.Boot$.runImpl(Boot.scala:41)
remote: 	at xsbt.boot.Boot$.main(Boot.scala:17)
remote: 	at xsbt.boot.Boot.main(Boot.scala)
remote: Error during sbt execution: java.io.IOException: No such file or directory
remote: An error occurred executing 'gear postreceive' (exit code: 1)
remote: Error message: CLIENT_ERROR: Failed to execute action hook 'build' for 123456789abcdef application xyz

To build your SBT application, you’ll need an .openshift/action_hooks/build file containing

#!/bin/bash
cd $OPENSHIFT_REPO_DIR
mkdir -p $OPENSHIFT_REPO_DIR/openshift_fakehome
./sbt -Duser.home=$OPENSHIFT_REPO_DIR/openshift_fakehome clean stage

This tells SBT to use a different (and writeable) home directory within the repository.

To start the DropWizard application, your .openshift/action_hooks/start file should contain

#!/bin/bash
nohup $OPENSHIFT_REPO_DIR/target/universal/stage/bin/your_app_name_here -Ddw.server.connector.bindHost=$OPENSHIFT_DIY_IP -Ddw.server.connector.port=$OPENSHIFT_DIY_PORT server $OPENSHIFT_REPO_DIR/config/local.yml &
echo $! > $OPENSHIFT_REPO_DIR/pid.pid

This binds the DropWizard service to the IP and port that the DIY cartridge requires you to bind to. We also store the process ID of this so we can kill it later.

And to kill the process (eg as part of a new git push), your .openshift/action_hooks/stop file should contain

#!/bin/bash
source $OPENSHIFT_CARTRIDGE_SDK_BASH
echo Killing PID $(cat $OPENSHIFT_REPO_DIR/pid.pid)
kill $(cat $OPENSHIFT_REPO_DIR/pid.pid)
rm $OPENSHIFT_REPO_DIR/pid.pid
exit 0

This reads the process ID to kill from the file and removes the file.

My only issue at the moment is that my Git Push frequently times out.

... log snipped ...
remote: [info] Compiling 9 Java sources to /var/lib/openshift/xyz/app-root/runtime/repo/target/scala-2.10/classes...
remote: [info] Main Java API documentation to /var/lib/openshift/xyz/app-root/runtime/repo/target/scala-2.10/api...
Connection to abc-xyz.rhcloud.com closed by remote host.
fatal: The remote end hung up unexpectedly

This requires me to push a new commit to kickstart the build. My SSH session to the same box is also disconnected at the same time, so I don’t know what happens there.

This is my personal blog - all views are my own.

Tagged with: , , , ,