Skip to content

Instantly share code, notes, and snippets.

@n2o
Last active March 18, 2023 12:41
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save n2o/bf1f26d922b29f1f08746188519c4f91 to your computer and use it in GitHub Desktop.
Save n2o/bf1f26d922b29f1f08746188519c4f91 to your computer and use it in GitHub Desktop.
Docker Multistage Build for a Clojure Application

A Docker Multistage Build reduces the complexity of a production image to a minimum. Since it is very easy to build jars from Clojure applications, we can just use an JRE to bring it to production.

Let's create a sample project using the app template with Leiningen:

lein new app foo
cd foo

Now, inside the project, we can create a Dockerfile build the project and create a production image, which comes with an JRE instead of a whole JDK:

FROM clojure:openjdk-11-lein-slim-buster AS BUILD
COPY . /code
WORKDIR /code
RUN lein uberjar

FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=BUILD /code/target/uberjar/*-standalone.jar ./app.jar
CMD ["java", "-jar", "app.jar"]

Build the image:

docker build -t foo .

And now let's start the application:

docker run --rm foo

and see "Hello, World!" on the terminal's output.

The size of the resulting image is "only" 209 MB big, which is kind of okayish, because we have a whole JRE packed inside. If we'd chosen a normal JDK build without Multistage, the resulting image would be around 431 MB big. This saves us some disk space and reduces potential attack vectors, because there are fewer possible binaries, which could be exploited. And also it is satisfactory to see the Megabytes get reduced by solely choosing a different base-image and copy the compiled files into this image.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment