Dockerizing a Clojure, Compojure, and HTTP Kit Web Application
November 29, 2014 -Docker is "an open platform for developers and sysadmins to build, ship, and run distributed applications. With Docker, developers can build any app in any language using any toolchain. Dockerized apps are completely portable and can run anywhere - colleagues’ OS X and Windows laptops, QA servers running Ubuntu in the cloud, and production data center VMs running Red Hat."
Here we will build a very simple web site using the Clojure Compojure and HTTP Kit libraries. The source code for this article is also available here.
Create a Compojure Application
First create a file named project.clj with the following contents:
(defproject hello-world "0.1.0"
:description "Compojure hello world web app"
:url "https://github.com/wtfleming/docker-compojure-hello-world"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.6.0"]
[compojure "1.2.1"]
[http-kit "2.1.16"]]
:main hello-world.core
:aot [hello-world.core])
And then create a file named src/hello_world/core.clj with these contents:
(ns hello-world.core
(:require [compojure.core :refer :all]
[org.httpkit.server :refer [run-server]])
(:gen-class))
(defroutes myapp
(GET "/" [] "Hello World"))
(defn -main []
(let [port (Integer/parseInt (or (System/getenv "PORT") "8080"))]
(run-server myapp {:port port})
(println (str "Listening on port " port))))
This is a very basic Compojure/HTTP Kit app with a single route that displays a web page with the contents "Hello World". We also check to see if an environment variable PORT has been defined, and if so bind to it, otherwise default to port 8080.
Now build with Leiningen.
$ lein uberjar
You could now run locally like this
$ java -jar target/hello-world-0.1.0-standalone.jar
Browse to http://localhost:8080 and you should see a page that displays "Hello World".
Create a Dockerfile
Now create a file called Dockerfile with these contents
#
# Dockerfile for a compojure hello world app
#
FROM java:openjdk-8-jre
MAINTAINER Will Fleming <wfleming77@gmail.com>
ENV REFRESHED_AT 2014-11-25
COPY target/hello-world-0.1.0-standalone.jar hello-world-0.1.0-standalone.jar
ENV PORT 4000
EXPOSE 4000
CMD ["java", "-jar", "hello-world-0.1.0-standalone.jar"]
The Dockerfile is a set of instructions to build a docker container.
-
We copy the jar file from our file system to the docker filesystem.
-
Define a environment variable PORT with the value 4000.
-
Expose port 4000 to other docker containers.
-
Provide a default command to be run when starting the container.
There is much more you can do, the Dockerfile documentation goes into further detail.
Build a Docker Image
Now lets build a Docker image.
$ docker build -t wtfleming/compojure-hello-world .
We can see that it was built:
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
wtfleming/compojure-hello-world latest b1c798937b9d 6 days ago 351.1 MB
We can use an image as the basis to launch a container.
Run a Docker container
$ docker run --rm -p 4000:4000 wtfleming/compojure-hello-world
Listening on port 4000
In the above we:
- Start a container from the wtfleming/compojure-hello-world image.
- --rm will delete the container when it stops
- -p will publish a container's port to the host
Open a web browser to http://localhost:4000 and you will see the page.
Browse to http://localhost:4000 or if you are on a Mac or Windows using boot2docker find the ip address like
$ boot2docker ip
The VM's Host only interface IP address is: 192.168.59.103
and browse to the ip provided by boot2docker like http://192.168.59.103:4000