Now you can stage classes and jars like this:
clojure -A:build -m package
The Dockerfile
uses a specific version of the relevant JDK image. Never use
fleeting tags like latest
for a production build - you want those to be
predictable and repeatable:
FROM openjdk:11.0.2-slim
ADD target/lib/lib /app/lib
ADD target/classes /app/classes
WORKDIR /app
CMD java $JAVA_OPTS -cp "classes:lib/*" our-app.core
Externalizing JVM parameters with $JAVA_OPTS
allows us to tweak runtime
characteristics without building a new artifact. Here's an example of setting it
from a Kubernetes deployment descriptor to configure JMX and heap memory:
containers:
- name: our-service
image: our.repo.com/our-app:ae31ade5ba
env:
- name: JAVA_OPTS
value: "-Dcom.sun.management.jmxremote.rmi.port=9090
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=9090
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.local.only=false
-Djava.rmi.server.hostname=localhost
-Xms128m
-Xmx128m"
We use a Makefile
to tie everything together, so we can do things like:
make docker # AOT compiles first if sources have changed
Here's something to get you started:
VERSION:=$(shell git rev-parse --short=10 HEAD)
target:
mkdir -p target
target/classes/our_app/core.class: deps.edn src/**/* target
clojure -A:build -m package
build: target/classes/our_app/core.class
docker: target/classes/our_app/core.class
docker build -t our-app:$(VERSION) .
clean:
rm -fr target
.PHONY: build docker clean
This is a very straight-forward approach that uses little tooling, has few
concepts to understand, no runtime component, and starts quickly.