We have been working on making it easier to deploy Clojure apps to Cloud Foundry [1]. Clojure is a functional language that runs on the JVM that allows rapid prototyping of applications while offering great support for integration with Java libraries. Many interesting projects–for example, Twitter’s own realtime processing framework Storm–are written in Clojure.
To help to run Clojure apps in Cloud Foundry, we have written a library called claude that you can use to easily access the different services offered by Cloud Foundry, like MongoDB or RabbitMQ.
Now let’s see how you can start deploying your Clojure apps to Cloud Foundry.
Deploying Your Clojure Apps to Cloud Foundry
We assume that you are using leiningen for your Clojure projects.
First you will add the latest version of claude into your project dependencies:
[claude “0.2.1-SNAPSHOT”] Then run lein deps
to obtain the project dependencies.
Once you have your project set up then you need to declare your project main
function:
:main clojure-demo.server
See this project project.clj
file for more details.
Then on your main namespace you need to add a :gen-class
like in this example:
(ns clojure-demo.server (:gen-class) (:require [noir.server :as server] [claude.core :as cf]))
If you are creating a web app then another tweak you need to perform is to inform your app of the port
in which it has to run. You can obtain the port from the VMC_APP_PORT
environment variable. Here’s an example:
(defn -main [& m] (let [mode (if (cf/cloudfoundry?) :prod :dev) port (Integer. (get (System/getenv) "VMC_APP_PORT" "8080"))] (server/start port {:mode mode :ns 'clojure-demo})))
Also, as you can see in that code snippet, we are using the claude.core/cloudfoundry?
helper to see if we are running in the cloud. In that case, we can set the web app environment to :prod
.
So far we have a basic Clojure project that can be run from a .jar file. Let’s create that jar file and deploy it to Cloud Foundry. We asume that you are already logged into Cloud Foundry using vmc
. Run the following commands inside your Clojure project folder:
mkdir cf lein uberjar cp target/clojure-demo-0.1.0-SNAPSHOT-standalone.jar cf/ cd cf
There we created a new folder to hold our app .jar
file. Now we are ready to deploy it. In this case, I will bind one instance of each service provided by Cloud Foundry. Therefore, you will see a lot of output in the following transcript. Let’s start with vmc push:
vmc push Would you like to deploy from the current directory? [Yn]: Y Application Name: clojure-demo Detected a Standalone Application, is this correct? [Yn]: Y 1: java 2: java7 3: node 4: node06 5: node08 6: ruby18 7: ruby19 Select Runtime : java7 Selected java7 Start Command: java $JAVA_OPTS -cp clojure-demo-0.1.0-SNAPSHOT-standalone.jar clojure_demo.server
Up to here we told vmc
that we are deploying a standalone application, that the runtime is java7
and we provided our startup command. Make sure to change the application name on your own deployment.
Let’s continue our deployment:
Application Deployed URL [None]: ${name}.${target-base} Memory reservation (128M, 256M, 512M, 1G, 2G) [512M]: 512 How many instances? [1]: 1
If we are deploying a web application, then we need to provide the URL for our app. In our case we let vmc build the URL based on our application name. In this case it will be under http://clojure-demo.cloudfoundry.com
. Keep in mind that you only need a URL if you are deploying a web app.
Now let’s create and bind one instance of each service type to our app:
Bind existing services to 'clojure-demo'? [yN]: N Create services to bind to 'clojure-demo'? [yN]: y 1: blob 2: mongodb 3: mysql 4: postgresql 5: rabbitmq 6: redis What kind of service?: 1 Specify the name of the service [blob-9dcdc]: Create another? [yN]: y 1: blob 2: mongodb 3: mysql 4: postgresql 5: rabbitmq 6: redis What kind of service?: 2 Specify the name of the service [mongodb-cb862]: Create another? [yN]: y 1: blob 2: mongodb 3: mysql 4: postgresql 5: rabbitmq 6: redis What kind of service?: 3 Specify the name of the service [mysql-2358b]: Create another? [yN]: y 1: blob 2: mongodb 3: mysql 4: postgresql 5: rabbitmq 6: redis What kind of service?: 4 Specify the name of the service [postgresql-de020]: Create another? [yN]: y 1: blob 2: mongodb 3: mysql 4: postgresql 5: rabbitmq 6: redis What kind of service?: 5 Specify the name of the service [rabbitmq-3422d]: Create another? [yN]: y 1: blob 2: mongodb 3: mysql 4: postgresql 5: rabbitmq 6: redis What kind of service?: 6 Specify the name of the service [redis-29cde]: Create another? [yN]: N
Note that we did this for our example’s sake. Your app might not need as many services or you might choose to not use any of them. It’s all up to you.
Now we probably want to save this configuration inside a manyfest.yml
file so we don’t need to type all that again the next time we deploy our app from scratch.
Would you like to save this configuration? [yN]: y Manifest written to manifest.yml.
Now vmc
will stage your app and it will start it automatically:
Creating Application: OK Creating Service [mongodb-cb862]: OK Binding Service [mongodb-cb862]: OK Creating Service [mysql-2358b]: OK Binding Service [mysql-2358b]: OK Creating Service [postgresql-de020]: OK Binding Service [postgresql-de020]: OK Creating Service [blob-9dcdc]: OK Binding Service [blob-9dcdc]: OK Creating Service [rabbitmq-3422d]: OK Binding Service [rabbitmq-3422d]: OK Creating Service [redis-29cde]: OK Binding Service [redis-29cde]: OK Uploading Application: Checking for available resources: OK Processing resources: OK Packing application: OK Uploading (5M): OK Push Status: OK Staging Application 'clojure-demo': OK Starting Application 'clojure-demo': OK
You can access a demo app here.
While this seems to be a little long, in fact we detailed every single step to get you up and running. To recap this is what we need did:
- Add the
claude
dependency to your project. - Add a
(:gen-class)
to your main namespace. This is a Clojure/Java requirement - Generate your uberjar.
- Deploy your app providing a start up command
And that’s it! Now create a free account at Cloud Foundry and let’s see your awesome Clojure apps deployed to Cloud Foundry!
1 *NOTE: At the time of this writing Clojure is unofficially supported at Cloud Foundry. *
About the Author