skip to content

How do you control the resulting image's name and push it directly to a registry from bootBuildImage / spring-boot:build-image?

level: middleimportance: must knowfreq 65%

answer

  1. imageName / <image><name>
  2. default = docker.io/library/name:version
  3. publish=true / --publishImage pushes
  4. docker.publishRegistry creds (username/password/url/token)
  5. registry host in name = push target

basics

~10 s

Set the image name (imageName in Gradle, <image><name> in Maven, or --imageName= / -Dspring-boot.build-image.imageName=). To push, enable publish (publish = true / <publish>true</publish>) and provide registry credentials via docker.publishRegistry.

solid answer

~30 s

The image name defaults to `docker.io/library/<name>:<version>`. Override it: Gradle `imageName.set("registry/repo:tag")` (or `--imageName` on the CLI); Maven `<image><name>registry/repo:tag</name></image>` (or `-Dspring-boot.build-image.imageName`). By default the image is written to the local daemon only. To push to a registry in the same step, enable publishing — Gradle `publish.set(true)` / `--publishImage`, Maven `<image><publish>true</publish></image>` / `-Dspring-boot.build-image.publish=true` — and supply credentials under `docker.publishRegistry` (username/password/token, or `url` for the registry). The image name's registry host must match the target registry. This lets CI build and push in one command without a separate `docker push`.

code

kotlin · 20 lines
kotlin
import org.springframework.boot.gradle.tasks.bundling.BootBuildImage

tasks.named<BootBuildImage>("bootBuildImage") {
    // Fully-qualified: host + repo + tag. The host decides where publish pushes.
    imageName.set("ghcr.io/acme/orders-service:${project.version}")

    // Push to the registry as part of the build (default is local-daemon only).
    publish.set(true)

    docker {
        publishRegistry {
            // Pull creds from CI env vars, never hard-code them.
            username.set(providers.environmentVariable("REGISTRY_USER"))
            password.set(providers.environmentVariable("REGISTRY_TOKEN"))
            url.set("https://ghcr.io")
        }
    }
}
// CLI equivalent:
// ./gradlew bootBuildImage --imageName=ghcr.io/acme/orders-service:1.4.0 --publishImage

go deeper

for a junior

Know that you can rename the image and that publish pushes it.

for a middle

Set fully-qualified names, enable publish, and wire publishRegistry creds from env.

for a senior

Distinguish builder vs publish registries and handle registry-specific auth (GHCR/ECR).

for a principal

Standardize naming/tagging and secret handling across all services' CI.

**Image name = registry + repository + tag.** A fully-qualified name looks like `ghcr.io/acme/orders-service:1.4.0` where `ghcr.io` is the **registry host**, `acme/orders-service` is the **repository**, and `1.4.0` is the **tag**. If you omit the host, tooling assumes Docker Hub (`docker.io/library/...`). **Default name:** If you set nothing, Spring Boot names the image `docker.io/library/<artifactId>:<version>` (Maven) or `docker.io/library/<project.name>:<version>` (Gradle). That `library/` namespace is Docker Hub's default; you almost always want to override it so the name points at *your* registry. **Setting the name:** - **Gradle** (`BootBuildImage` task): `imageName.set("ghcr.io/acme/orders:${version}")`, or on the command line `./gradlew bootBuildImage --imageName=ghcr.io/acme/orders:1.4.0`. - **Maven**: in the plugin config `<image><name>ghcr.io/acme/orders:${project.version}</name></image>`, or `./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=ghcr.io/acme/orders:1.4.0`. **Publishing (pushing) to a registry:** By default the finished image is loaded into the **local Docker daemon** and nothing is pushed. To push as part of the build: - **Gradle:** `publish.set(true)` on the task, or `--publishImage` on the CLI. - **Maven:** `<image><publish>true</publish></image>`, or `-Dspring-boot.build-image.publish=true`. When `publish=true`, the **registry host in the image name is where it gets pushed** — so `imageName` must already be fully-qualified with the correct host. **Credentials:** Publishing needs auth. Spring Boot has *two* registry credential blocks under the `docker` configuration: - `docker.builderRegistry` — creds used to **pull** the builder/run images (only needed if those live in a private registry). - `docker.publishRegistry` — creds used to **push** your app image. Each accepts `username`, `password`, `url`, `email`, or a `token` (for token-based auth). Example (Gradle): ```kotlin tasks.named<BootBuildImage>("bootBuildImage") { imageName.set("ghcr.io/acme/orders:$version") publish.set(true) docker { publishRegistry { username.set(providers.environmentVariable("REGISTRY_USER")) password.set(providers.environmentVariable("REGISTRY_TOKEN")) url.set("https://ghcr.io") } } } ``` Maven has the equivalent `<docker><publishRegistry>...</publishRegistry></docker>`, and you can also pass credentials via CLI properties like `-Dspring-boot.build-image.publishRegistry.username=...`. **Gotchas:** - Setting `publish=true` but leaving the name at the `docker.io/library/...` default will try to push to Docker Hub — usually not what you want. Always fully-qualify the name. - Credentials must have push scope on the target repo; a common CI failure is a token that can pull but not push. - Registries like GHCR/ECR may require the username to be a specific value (e.g. GHCR uses your GitHub username or `USERNAME`, ECR uses `AWS`), or a helper to fetch a short-lived token. - Publish pushes exactly the one name/tag in `imageName`; if you want multiple tags you tag/push separately or re-run with another name. **When to use publish:** CI pipelines — build and push in one step, avoiding a separate `docker login` + `docker push`. Locally, you usually leave `publish` off and just load into your daemon.

  • If you set publish=true but leave imageName at its default, where does it try to push?
    To Docker Hub under `docker.io/library/<name>` — because the registry host is taken from the image name. That is almost never intended, so always fully-qualify the name before publishing.
  • What's the difference between docker.builderRegistry and docker.publishRegistry?
    builderRegistry authenticates pulling the builder/run images (needed only if they're private); publishRegistry authenticates pushing your finished application image.

saying these in an interview costs you the question

  • Thinking bootBuildImage pushes to a registry by default
  • Confusing builderRegistry (pull) with publishRegistry (push)
  • Believing you must run a separate `docker push` — publish does it in-step
  • Putting credentials in the image name or committing them

context