skip to content

Walk through the jib { from, to, container } DSL: what does each block configure and what are the key fields?

level: middleimportance: must knowfreq 48%

answer

  1. from = base image + platforms
  2. to = image name + tags + auth
  3. container = mainClass, jvmFlags, ports, user, labels
  4. mainClass auto-detected, set for Boot/Kotlin
  5. entrypoint INHERIT keeps base

basics

~10 s

from sets the base image. to sets the target image name/tags and auth. container configures runtime: jvmFlags, mainClass, ports, entrypoint, environment, labels.

solid answer

~40 s

The `jib { }` block has three main sections. **`from`** chooses the base image (`image = "eclipse-temurin:21-jre"`) and its `auth`/`platforms` (for multi-arch). **`to`** names the output: `image` (the full registry/repo:tag), extra `tags`, and registry `auth`/credHelper. **`container`** describes how the JVM app runs inside the image: `mainClass`, `jvmFlags` (e.g. `-Xms512m`), `ports`, `environment`, `labels`, `user`, `workingDirectory`, `creationTime`, and `entrypoint` (set to `INHERIT` to reuse the base image's entrypoint, or omit to let Jib generate the java launch). Jib auto-detects `mainClass` from the build when unambiguous, but you set it explicitly for Spring Boot/Kotlin (`AppKt`) apps. These blocks are the whole contract — no Dockerfile instructions involved.

code

kotlin · 13 lines
kotlin
jib {
    from { image = "eclipse-temurin:21-jre" }
    to {
        image = "ghcr.io/acme/billing"
        tags = setOf("latest", project.version.toString())
    }
    container {
        mainClass = "com.acme.billing.AppKt"
        jvmFlags = listOf("-XX:MaxRAMPercentage=75")
        ports = listOf("8080")
        user = "1000:1000"
    }
}

go deeper

for a junior

Know from = base, to = target name, container = runtime settings like mainClass.

for a middle

List the key fields per block and know mainClass/jvmFlags/ports/user live in container.

for a senior

Use container.user and labels for hardening/metadata and explain multi-tag pushes via to.tags.

for a principal

Standardize a shared Jib convention (base image, non-root user, OCI labels) across services via a convention plugin.

## The three configuration blocks ### `from` — the base image Controls what your app layers sit on top of. - `image` — base reference, e.g. `eclipse-temurin:21-jre`. If omitted, Jib uses a default distroless-style JRE base. - `auth { username/password }` or `credHelper` — credentials to pull a private base. - `platforms { platform { architecture = "arm64"; os = "linux" } }` — build a multi-arch image. ### `to` — the destination image Controls naming and where it is pushed. - `image` — full target, e.g. `ghcr.io/acme/billing:1.4.0`. - `tags` — additional tags applied to the same digest, e.g. `setOf("latest", gitSha)`. - `auth { }` / `credHelper` — registry credentials for the push. ### `container` — runtime configuration This is the equivalent of the runtime-affecting Dockerfile instructions. - `mainClass` — entrypoint class. Auto-detected when unambiguous; set explicitly for Spring Boot (`org.springframework.boot.loader...` is handled by the Boot integration) or Kotlin (`com.acme.AppKt`). - `jvmFlags` — list of JVM args baked into the launch command, e.g. `listOf("-Xms256m", "-XX:+UseG1GC")`. - `ports` — exposed ports metadata, e.g. `listOf("8080")`. - `environment` — env vars map. - `labels` — OCI image labels (useful for org.opencontainers.* metadata). - `user` — run as a non-root user, e.g. `"1000:1000"`. - `workingDirectory`, `creationTime`, `format` (`OCI` or `Docker`). - `entrypoint` — set to `"INHERIT"` to keep the base image's entrypoint, or leave default so Jib builds the `java -cp ... mainClass` launcher. ## Example ```kotlin jib { from { image = "eclipse-temurin:21-jre" } to { image = "ghcr.io/acme/billing" tags = setOf("latest", project.version.toString()) } container { mainClass = "com.acme.billing.AppKt" jvmFlags = listOf("-Xms256m", "-XX:MaxRAMPercentage=75") ports = listOf("8080") user = "1000:1000" labels = mapOf("org.opencontainers.image.source" to "https://github.com/acme/billing") } } ``` ## Why this matters Everything about the produced image — base, name, JVM tuning, security user, metadata — lives in one typed block, version-controlled with the build, with no shell scripting. That makes images reproducible and reviewable.

  • Where do you set JVM memory flags for the running container?
    In `container { jvmFlags = listOf("-Xms...", "-XX:MaxRAMPercentage=...") }`. They are baked into the generated launch command.
  • How do you run the container as a non-root user with Jib?
    Set `container { user = "1000:1000" }` (uid:gid). Jib bakes that into the image config.
  • When must you set mainClass explicitly?
    When Jib cannot unambiguously detect it — multiple main methods, or Kotlin `AppKt` / Spring Boot layouts. Otherwise auto-detection works.

saying these in an interview costs you the question

  • Putting base-image choice under `to` instead of `from`.
  • Thinking jvmFlags belong in `from` or `to` rather than `container`.
  • Assuming mainClass is always auto-detected (fails with multiple mains).

context