By Tzach Livyatan
Clojure applications run on the JVM, so they’re usually simple to run on OSv. We have hello world in Clojure running, but this time I wanted to port a real, non-toy, Clojure application. I chose Riemann, a widely-used application for aggregating system events (and more).
Following the Capstan guideline, I added a Capstanfile to the project. Here are the parts of Capstanfile you need to know about:
- Set the base image. In this case I chose a base image with Java (open-jdk)
- Build the jar file, taking advantage of the
lein uberjarcommand, which packages the application with all dependencies into one jar file.
build: lein uberjar
- Copy the build artifacts to the base image, producing a new image:
files: /riemann.jar: ./target/riemann-0.2.5-SNAPSHOT-standalone.jar /riemann.config: ./riemann.config
I also copy the config file, which Riemann will look for.
- The run command for the VM is executed when the VM starts.
cmdline: /java.so -jar /riemann.jar
That’s it. Done with the Capstanfile.
Let’s test it!
>capstan run WARN [2014-04-13 14:11:22,029] Thread-9 - riemann.core - instrumentation service caught java.io.IOException: Cannot run program "hostname": error=0, vfork failed at java.lang.ProcessBuilder.start(ProcessBuilder.java:1041) at java.lang.Runtime.exec(Runtime.java:617) at clojure.java.shell$sh.doInvoke(shell.clj:116) at clojure.lang.RestFn.invoke(RestFn.java:408)
No luck. It turns out that Riemann is using
which uses vfork to run a child process. On any OS its not very efficient to fork just to get the hostname, and on current OSv it simply won’t work. To bypass the problem, I replace this call with:
which uses a Java
Let’s try again
This time it works, but how do I test it and connect to it?
Let’s use Capstan port forwarding
capstan run -f 5555:5555 -f 5556:5556
This will forward host ports 5555 and 5556 to the corresponding ports on the OSv VM.
Now we can switch to another terminal and run:
to generate traffic for Riemann and
to launch a Riemann web GUI. Here is how it looks: