Skip to content

Instantly share code, notes, and snippets.

@xhanin
Created November 12, 2022 19:32
Show Gist options
  • Save xhanin/ac6060a4e447be388d065a0ed2cf0cef to your computer and use it in GitHub Desktop.
Save xhanin/ac6060a4e447be388d065a0ed2cf0cef to your computer and use it in GitHub Desktop.

intent

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

how to

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"]

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