Clojure Docker Web Apps

If you’re interested in making a commercial grade Clojure web app that deploys as a Docker container, this is the tutorial for you.

Prerequisites: You will need Leiningen and Docker installed.

First step needed is to create a Clojure web app template project. I used the following command.

This creates a Clojure web app using the Luminus Framework, Reitit for mapping of incoming requests to the proper handlers, HTTP Kit for HTTP handling, MySQL for JDBC connections to our MySQL database, Swagger for API support, and Buddy for authentication middleware. Your new web app is in the directory, mywebapp .

Before starting your web app, your database connection needs to be configured in dev-config.edn . Something similar to the following should be added to that *.edn  file.


At this point it is important to note that you will run into all kinds of problems with Docker if you try to use localhost (or 127.0.0.1) with docker for your database connection. Instead, configure it to use the IP address of your computer, and configure your MySQL user to accept connections from everywhere. This simulates using a remote MySQL server.

nrepl  is another consideration when creating Docker images for Clojure apps, including our web app. If you want to expose a remote REPL from inside the docker container, you will need to specify an :nrepl-port  and an :nrepl-bind  address. I recommend adding the following configuration lines to your *.edn  config file.


To start up the web app cd  to the mywebapp  directory and enter lein run . You should then be able to navigate to http://localhost:3000/  from your web browser. When you’re done playing with the new web app, use control-c to stop the server.

Okay! You have a working web app. Now let’s containerize it.

We need an uber jar when building our docker container. In turn, to build the docker container, we need to embed the prod configuration file. Configure your env/prod/resources/config.edn  to match your dev-config.edn

Now create an uberjar for mywebapp. An uberjar is a giant JAR file containing every dependency for mywebapp. Run the following command to create the uberjar.

We’re ready for the docker build, … almost. First we need to get our Dockerfile  configured for our build. Here’s my Dockerfile .


This Dockerfile  uses Java 11, and exposes port 3000 for the webserver and port 7000 for the remote REPL connections.

Next, we’ll check that our initial Dockerfile is building.

As an alternative build, use the -t for naming/tagging the docker image you’re building.

Finally, run the docker container locally with the following command.

The image ID comes from the docker build. Look for a line similar to the following in your output.

=> => writing image sha256:0c826b218048658976b05f82a8160fa7c61aaedb769307d78b93a34d13b46479

The part after sha256:  is your image ID.

Just for completeness, let’s go over the rest of the docker run options used above.

-it  allows interactive processes like shells.

--rm  removes containers when they are shutdown. This is desirable when testing, but probably not wanted in a production environment.

--name  gives a friendly name to the container started by docker run .

-p  exposes a port of the app running in the docker container to the the rest of the network.

In a production environment, you’re likely to want to run docker containers in detached mode. Use -d  to run your container in the background.

There you go. A complete Dockerized Clojure web app. Once you work through this tutorial, you should have enough information to create your own Docker web apps with Clojure. Enjoy!

 

Leave a Reply

Your email address will not be published.