How to Deploy Kotlin to Docker Without Writing a Dockerfile
You can containerize any Kotlin application without writing a Dockerfile using migetpacks. It auto-detects Kotlin projects from build.gradle.kts or .kt files, uses the Gradle wrapper for correct versioning, and produces an optimized Eclipse Temurin JRE image. One command, zero configuration.
Why Is Writing a Dockerfile for Kotlin So Complicated?
A production-ready Kotlin Dockerfile requires:
- Multi-stage builds to separate Gradle from runtime
- JDK version selection (17, 21, etc.)
- Gradle wrapper handling for version consistency
- Proper caching of Gradle dependencies
- Choosing between JDK and JRE runtime images
- JVM memory configuration for containers
The Kotlin/Gradle combination with its DSL files and wrapper scripts makes Docker configuration verbose and error-prone.
How Do I Containerize a Kotlin App Without a Dockerfile?
Open your terminal, navigate to your Kotlin project, and run:
cd ~/projects/my-kotlin-api
docker run --rm \
-v "$PWD":/workspace/source \
-v /var/run/docker.sock:/var/run/docker.sock \
-e OUTPUT_IMAGE=my-kotlin-api:latest \
miget/migetpacks:latest
That's it. migetpacks will:
- Detect Kotlin from
build.gradle.kts,settings.gradle.kts, or.ktfiles - Read Kotlin version from
gradle.propertiesor build files - Use Gradle wrapper if present
- Run
gradle buildwith dependency caching - Output a slim JRE-based production image
How Does migetpacks Detect Kotlin?
migetpacks detects a Kotlin application when any of these conditions are met:
settings.gradle.ktsexists.ktfiles exist insrc/directorybuild.gradle.ktscontains thekotlinpluginbuild.gradle(Groovy DSL) contains a Kotlin plugin reference
Kotlin detection takes priority over Java/Gradle detection.
How Are Versions Detected?
Kotlin Version
| Source | Example |
|---|---|
.kotlin-version | 2.1.0 |
gradle.properties (kotlin.version) | kotlin.version=2.1.0 |
build.gradle.kts (plugin version) | kotlin("jvm") version "2.1.0" |
| Default | Latest stable |
Java Version
| Source | Example |
|---|---|
system.properties | java.runtime.version=21 |
| Default | 21 |
What Does the Generated Dockerfile Look Like?
# Build stage
FROM gradle:jdk21 AS builder
WORKDIR /build
ENV JAVA_TOOL_OPTIONS="-Dfile.encoding=UTF-8"
COPY gradlew ./
COPY gradle/ gradle/
COPY build.gradle* settings.gradle* ./
RUN ./gradlew dependencies --no-daemon || true
COPY . .
RUN ./gradlew build -x test --no-daemon \
&& rm -rf src/ gradle/ gradlew* build.gradle* settings.gradle*
# Runtime stage
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=builder --chown=1000:1000 /build /app
You never write or maintain this file - migetpacks handles it automatically.
What JVM Configuration Is Applied?
migetpacks sets production-optimized JVM settings:
| Variable | Value |
|---|---|
JAVA_OPTS | -Dfile.encoding=UTF-8 -XX:MaxRAMPercentage=80.0 |
JAVA_TOOL_OPTIONS | -Dfile.encoding=UTF-8 |
How Do I Build a Ktor App?
Ktor works out of the box:
cd ~/projects/my-ktor-app
docker run --rm \
-v "$PWD":/workspace/source \
-v /var/run/docker.sock:/var/run/docker.sock \
-e OUTPUT_IMAGE=my-ktor:latest \
miget/migetpacks:latest
The default run command:
java -jar build/libs/*.jar
How Do I Build Secure Distroless Images?
Enable Docker Hardened Images for minimal containers:
docker run --rm \
-v "$PWD":/workspace/source \
-v /var/run/docker.sock:/var/run/docker.sock \
-e OUTPUT_IMAGE=my-app:latest \
-e USE_DHI=true \
miget/migetpacks:latest
DHI uses distroless Eclipse Temurin images - no shell, no package manager, minimal attack surface.
Next Steps
- Full Kotlin documentation - version detection, Gradle, DHI
- Deploy on Miget - unlimited apps, one price
- Star on GitHub - migetpacks is open source
- Related guides: Java, Scala, Clojure