Heroku

How It Works

Getting Started with Clojure on Heroku/Cedar

Last Updated: 03 January 2012

cedar clojure

Table of Contents

This quickstart will get you going with Clojure and the Ring web library on the Cedar stack.

Prerequisites

  • Basic Clojure knowledge, including an installed version of Leiningen and a JVM.
  • Your application must be compatible with Leiningen 1.6.2.
  • Your application must run on the OpenJDK version 6.
  • A Heroku user account. Signup is free and instant.

Local Workstation Setup

We’ll start by setting up your local workstation with the Heroku command-line client and the Git revision control system; and then logging into Heroku to upload your ssh public key. If you’ve used Heroku before and already have a working local setup, skip to the next section.

If you have... Install with...
Mac OS X Download OS X package
Windows Download Windows .exe installer
Ubuntu Linux apt-get repository
Other Tarball (add contents to your $PATH)

Once installed, you’ll have access to the heroku command from your command shell. Log in using the email address and password you used when creating your Heroku account:

$ heroku login
Enter your Heroku credentials.
Email: adam@example.com
Password: 
Could not find an existing public key.
Would you like to generate one? [Yn] 
Generating new SSH public key.
Uploading ssh public key /Users/adam/.ssh/id_rsa.pub

Press enter at the prompt to upload your existing ssh key or create a new one, used for pushing code later on.

Write Your App

You may be starting from an existing app. If not, here’s a simple “hello, world” sourcefile you can use:

src/demo/web.clj

(ns demo.web
  (:use ring.adapter.jetty))

(defn app [req]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body "Hello, world"})

(defn -main [port]
  (run-jetty app {:port (Integer. port)}))

Declare Dependencies In project.clj

Cedar recognizes an app as Clojure by the existence of a project.clj file.

Here’s an example project.clj for the Clojure/Ring app we created above:

project.clj

(defproject hello-world "0.0.1"
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [ring/ring-jetty-adapter "1.0.1"]])

Run lein deps to install your dependencies locally.

Prevent build artifacts from going into revision control by creating this file:

.gitignore

lib

Declare Process Types With Foreman/Procfile

To run your web process, you need to declare what command to use. In this case, we simply need to execute our single Clojure namespace. We’ll use Procfile to declare how our web process type is run.

Here’s a Procfile for the sample app we’ve been working on:

web: lein run -m demo.web $PORT

Now that you have a Procfile, you can start your application with Foreman:

$ foreman start

Your app will come up on port 5000. Test that it’s working with curl or a web browser, then Ctrl-C to exit.

Store Your App in Git

We now have the three major components of our app: dependencies in project.clj, process types in Procfile, and our application source in src/demo/web.clj. Let’s put it into Git:

$ git init
$ git add .
$ git commit -m "init"

Deploy to Heroku/Cedar

Create the app on the Cedar stack:

$ heroku create --stack cedar
Creating glowing-snow-27... done
Created http://glowing-snow-27.herokuapp.com/ | git@heroku.com:glowing-snow-27.git
Git remote heroku added

Deploy your code:

$ git push heroku master
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (7/7), 710 bytes, done.
Total 7 (delta 0), reused 0 (delta 0)

-----> Heroku receiving push
-----> Clojure app detected
-----> Installing Leiningen
       Downloading: leiningen-1.6.2-standalone.jar
       Downloading: rlwrap-0.3.7
       Writing: lein script
-----> Installing dependencies with Leiningen
       Running: LEIN_NO_DEV=y lein deps
       Downloading: org/clojure/clojure/1.3.0/clojure-1.3.0.pom from central
       Downloading: ring/ring-jetty-adapter/1.0.1/ring-jetty-adapter-1.0.1.pom from central
       ...
       Copying 11 files to /tmp/build_22n0pvoq4rj3p/lib
-----> Procfile declares process types -> web
       Compiled slug size is 3.9MB
-----> Launching... done, v1
       http://glowing-snow-27.herokuapp.com deployed to Heroku

To git@heroku.com:glowing-snow-27.git
 * [new branch]      master -> master

Before looking at the app on the web, we’ll need to scale the web process:

$ heroku ps:scale web=1
Scaling web processes... done, now running 1

Now, let’s check the state of the app’s processes:

$ heroku ps
Process       State               Command
------------  ------------------  --------------------------------------------
web.1         up for 10s          lein run -m demo.web

The web process is up. Review the logs for more information:

$ heroku logs
2011-03-16T03:28:32-07:00 heroku[web.1]: Running process with command: `lein run -m demo.web`
2011-03-16T03:28:37-07:00 app[web.1]: 2011-03-16 10:28:37.181:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2011-03-16T03:28:37-07:00 app[web.1]: 2011-03-16 10:28:37.182:INFO::jetty-6.1.26
2011-03-16T03:28:40-07:00 app[web.1]: 2011-03-16 10:28:40.223:INFO::Started SocketConnector@0.0.0.0:20184
2011-03-16T03:28:40-07:00 heroku[web.1]: State changed from starting to up
...

Looks good. We can now visit the app with heroku open.

Console

Cedar allows you to launch a REPL process attached to your local terminal for experimenting in your app’s environment:

Running heroku run lein repl uses a simplified version of the repl task provided by Leiningen.

$ heroku run lein repl
Running lein repl attached to terminal... up, run.1
Clojure 1.3.0
user=> 

This console has your application code available. For example:

user=> (require 'demo.web)   
nil
user=> (demo.web/app {})
{:status 200, :headers {"Content-Type" "text/plain"}, :body "Hello, world"}

One-off Scripts

You can run a one-off Clojure script attached to the terminal in the same way, as long as the script exists in your deployed app. Try making a small script that prints to the console and exits:

src/demo/hi.clj

(ns demo.hi)

(defn -main [& args]
  (println "Hello there"))

Commit and deploy this new code:

$ git add src/demo/hi.clj
$ git commit -m "hi"
$ git push heroku master

Run the script with heroku run:

$ heroku run lein run -m demo.hi
Running lein run -m demo.hi attached to terminal... up, run.2
Hello there

Using a SQL Database

By default, Clojure apps aren’t given a SQL database. This is because you might want to use a NoSQL database like Redis or CouchDB, or (as in the case of our sample app above) you don’t need any database at all.

If you do need a SQL database for your app, request one explicitly:

$ heroku addons:add shared-database

Further Reading