produce a docker image with 3 main layers:
- OS / java - rarely changes, good caching and sharing among apps in a kubernetes cluster
- dependencies - changes are not too frequent, good caching among app versions
- app jar - changes with every version, but should be quite compact
in build.gradle.kts
:
plugins {
// use application plugin to package the app and start script
application
// and palantir docker plugin to build docker image
id("com.palantir.docker")
}
val archiveBaseName = "my-app"
val jarFileName = "${project.name}-$version.jar"
// disable zip packaging, not used
tasks.getByName<Zip>("distZip").enabled = false
// exclude main app jar from application tar
tasks.getByName<Tar>("distTar").exclude("**/$jarFileName")
// setup application as usual
application {
mainClass.set("com.acme.my.full.qualified.MyAppName")
applicationName = archiveBaseName
}
docker {
name = "${dockerRepository()}/my-docker-image-app:$version"
setDockerfile(File("Dockerfile"))
buildArgs(
mapOf(
// to access the app tar with dependencies and start script
"APPLICATION_ARCHIVE_FILE_NAME" to "${archiveBaseName}-${version}.tar",
// to access the main app jar
"APPLICATION_JAR_FILE_NAME" to "$jarFileName",
// the name of the folder within the tar
"APPLICATION_FOLDER_NAME" to "${archiveBaseName}-${version}"
)
)
// to access the app distrib tar
files(tasks.distTar.get().outputs.files)
// and the main jar
files(tasks.jar.get().outputs.files)
}
the Dockerfile
:
# choose base image, eclipse temurin 17 jre alpine is a good candidate, pretty small
FROM eclipse-temurin:17-jre-alpine
# specify the args provided by gradle docker build
ARG APPLICATION_ARCHIVE_FILE_NAME
ARG APPLICATION_JAR_FILE_NAME
ARG APPLICATION_FOLDER_NAME
# add the application distrib tar with dependencies and start script in a layer
ADD $APPLICATION_ARCHIVE_FILE_NAME /app
# then add the application main jar in a separate layer
ADD $APPLICATION_JAR_FILE_NAME /app/$APPLICATION_FOLDER_NAME/lib
# now we can set the workdir
WORKDIR /app/$APPLICATION_FOLDER_NAME
# and set the start script - adapt to your own project
CMD ["bin/my-app-start-script"]