Skip to content

Invalid reference format error when tagging images using Podman #35358

@johnnywalker

Description

@johnnywalker

Problem

The bootBuildImage task encounters an error configuring tags when using Podman instead of Docker.

Example config:

val registry = "example.org"
val channel: String by project
val latestTag = if (channel.isBlank()) "latest" else "$channel-latest"

tasks {
    bootBuildImage {
        buildpacks.set(listOf("urn:cnb:builder:paketo-buildpacks/java", "gcr.io/paketo-buildpacks/health-checker:latest"))
        environment.set(environment.get() + mapOf("BP_HEALTH_CHECKER_ENABLED" to "true"))
        imageName.set("$registry/${rootProject.name}-${project.name}:${project.version}")
        tags.set(listOf("$registry/${rootProject.name}-${project.name}:$latestTag"))
    }
}

Error:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':example:bootBuildImage'.
> Docker API call to 'localhost/v1.24/images/example.org/example-service:1.0.0-beta.1/tag?repo=example.org%2Fexample-service%3Abeta-latest' failed with status code 500 "Internal Server Error" and message "normalizing image: normalizing name for compat API: invalid reference format"

Diagnosis

DockerApi::tag uses a single query parameter (repo) for the target reference:

The Docker Engine API accepts both repo and tag parameters, but it parses repo if tag is not specified. Podman does not currently support this behavior.

API reference: https://docs.podman.io/en/v3.2.3/_static/api.html#tag/images/operation/ImageTagLibpod

Example request (current behavior)

This fails with podman 4.5.0:

curl --unix-socket /var/run/docker.sock -v -X POST \
  "http://localhost/v1.24/images/example.org/example-service:1.0.0/tag?repo=example.org%2Fexample-service%3Alatest"

Podman returns the following:

{
  "cause": "normalizing name for compat API: invalid reference format",
  "message": "normalizing image: normalizing name for compat API: invalid reference format",
  "response": 500
}

Updated request (desired behavior)

This request includes separate repo and tag parameters and works with podman 4.5.0:

curl --unix-socket /var/run/docker.sock -v -X POST \
  "http://localhost/v1.24/images/example.org/example-service:1.0.0/tag?repo=example.org%2Fexample-service&tag=latest"

Workaround

import org.springframework.boot.buildpack.platform.docker.transport.HttpTransport

tasks {
    bootBuildImage {
        buildpacks.set(
            listOf(
                "urn:cnb:builder:paketo-buildpacks/java",
                "gcr.io/paketo-buildpacks/health-checker:latest"
            )
        )
        environment.set(environment.get() + mapOf("BP_HEALTH_CHECKER_ENABLED" to "true"))
        imageName.set("$registry/${rootProject.name}-${project.name}:${project.version}")
        finalizedBy("tagLatest")
    }

    register("tagLatest") {
        doLast {
            val source = bootBuildImage.get().imageName.get()
            val target = object {
                val repo = "$registry/${rootProject.name}-${project.name}"
                val tag = latestTag
                override fun toString() = "$repo:$tag"
            }
            URIBuilder("/v1.24/images/$source/tag")
                .addParameter("repo", target.repo)
                .addParameter("tag", target.tag)
                .build().let { uri ->
                    HttpTransport.create(null).post(uri).close()
                }.also {
                    println("Tagged $source as $target")
                }
        }
    }
}

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions