Deploying Clojure Apps to Heroku with Docker
In this post, you’ll learn how to deploy a Docker-based Clojure application to Heroku using the Heroku Docker CLI. We’ll use the Immutant Feature Demo as an example, but you can follow along with any Clojure application as long as it uses Leiningen to build an uberjar. This is a Mac and Linux guide only (until Docker supports docker-compose
on Windows).
Prerequisites
You’ll need a few pieces of software before you get started:
- Docker (easily installed with the Docker Toolbox)
- Docker Compose (You’ll have this if you installed the Toolbox)
- Heroku Toolbelt
You’ll also need to create a free Heroku account. Then login from the terminal like so:
Once that’s complete, you can install the Heroku Docker CLI with this command:
Now you’re ready to deploy.
Deploying an App
To begin, clone the Immutant demo app to your local machine (if you’d prefer a bare-bones Clojure app you can substitute this Ring app):
The app is already prepared for Heroku. It contains a Procfile
, which tells Heroku how to run the app, and an app.json
file that contains some meta-data about the app. The important part of the app.json
file is the "image"
element, shown below:
The "image"
element is what Heroku uses to determine the base Docker image to run the container from.
The "addons"
element determines what additional services will be attached to your container. The Heroku
currently supports Postgres, Redis and a few others services with more to come.
Given this configuration, we can initialize the app with the following command:
This created a Dockerfile
based on the heroku/clojure
image and a docker-compose.yml
that constructs the environment (including a local database running in a Docker container).
Now run this command to start the application in a container:
The first time you run this it will take a while as Leiningen downloads the app’s dependencies into the Docker container. But don’t worry, they’ll be cached.
When the container has started, you’ll see some output like this:
That’s Immutant demonstrating it’s scheduling feature.
Open the app in a browser by running this command:
After you’ve played around with some of the features, like WebSockets, you can deploy the app to Heroku. First, provision a new app thusly:
And deploy to Heroku with the Docker CLI
Then you can open the app with this command:
Note that when using WebSockets in Firefox, you’ll need to use an http://
addres instead of the https://
that Heroku defaults to.
Development Workflow
In your normal workflow, you’d want to make some changes and see them appear in the Docker container. We’ll demonstrate how that works. Open the src/demo/scheduling.clj
file and look for this code:
Change the "beep"
string on the first line to "crocodile"
.
Save the file, and then run these commands to rebuild the image:
Open the app in a browser again and navigate to the /hello
path. You’ll see your changes. Each time modify your app, you need to re-build the image and then launch the up
command. You can also get terminal access to the image by running the shell
command thusly:
From this shell, you can run one-off tasks like database migrations.
Heroku’s Docker support is currently in beta. As we work to make the integration better, we’d love to hear your feedback so we can focus on building the things you need. Feel free to reach out to me directly with you thoughts and ideas.
You can visit the Heroku Dev Center for more information on Heroku’s Docker CLI. And you can learn more about Immutant and Docker from their respective documentation sites. You can also find more information about deploying Clojure apps to Heroku on the Dev Center.