Docker
Curie generates a Dockerfile alongside your JAR — no plugin, no Buildpacks, no jib. The output is layer-friendly: dep JARs land in their own layer so app-code changes don't invalidate the dependency layer.
When it runs
curie build on an [application] project always produces the JAR. When Docker is in scope (curie run, or future curie docker commands), Curie writes a Dockerfile + .dockerignore next to the JAR in target/. Library projects ([library]) never produce a Dockerfile — they're not runnable on their own.
Configuration
[application] name = "greeter" version = "0.1.0" mainClass = "com.example.Greeter" [docker] baseImage = "eclipse-temurin:21-jre-alpine"
The only knob is baseImage. The default is eclipse-temurin:21-jre — a JRE-sized image is much smaller than a JDK image, and the runtime needs no compiler. Switch to -alpine for a smaller image, or to a distroless base for hardened deployments; whatever you choose is interpolated verbatim into the FROM line.
Generated Dockerfile
For an application with no dependencies, Curie writes:
FROM eclipse-temurin:21-jre WORKDIR /app COPY greeter-0.1.0.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]
When the application has [dependencies], Curie copies the resolved dep JARs into target/libs/ at package time and adds a COPY libs/ libs/ step before the app JAR is copied. Docker caches each COPY as its own layer, so the dep layer is reused across rebuilds whenever your direct dependencies don't change — only the small app-JAR layer is rebuilt on a code edit.
FROM eclipse-temurin:21-jre WORKDIR /app COPY libs/ libs/ COPY greeter-0.1.0.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]
The JAR's Class-Path manifest entry points at libs/, so java -jar app.jar finds every transitive dep without a wrapper script.
.dockerignore
Curie also generates target/.dockerignore that excludes everything by default and re-whitelists only the files the build needs:
* !greeter-0.1.0.jar !libs/
This keeps the build context small and stops accidental secrets in target/ (test outputs, intermediate class files) from being baked into the image.
Running
curie run defaults to Docker: it builds the image and launches a container in one step. Pass --no-docker to invoke java -jar directly against the host JRE — useful for quick local sanity checks where you don't care about the container.
Compile up to date Package up to date Docker image greeter:0.1.0 (via target/Dockerfile) Run docker run --rm greeter:0.1.0 Hello from greeter.
Incremental Docker builds
The Dockerfile + .dockerignore are stamped against their inputs: the JAR mtime, the libs/ directory mtime, and Curie.toml's [docker] table. If none of those moved since the last image build, Curie skips the docker build invocation entirely.