gesellix / gradle-docker-plugin

Gradle Docker plugin
MIT License
79 stars 17 forks source link

Tagging does not work with buildParam "t" in DockerBuildTask #363

Closed antimatter84 closed 9 months ago

antimatter84 commented 10 months ago

I use DockerBuildTask in Gradle to create a Docker image tarball. However, the image is not tagged and loading it in my docker registry will require manuall tagging, because docker images displays it as <none>. As I understand from the examples and source code, setting imageName should suffice:

tasks.register<DockerBuildTask>("buildImage") {
    imageName.set("myApp:1.2.3")

    // ...
}

Alternatively, I tried the "t" buildParam which was added by upcFrost about 6 years ago:

tasks.register<DockerBuildTask>("buildImage") {
    //imageName.set("myApp:1.2.3")
    buildParams.putAll(mapOf(
        "rm" to true,
        "t" to "myApp:1.2.3"
    ))

    // ...
}

However, none of these attempts work. My expectation is that the manifest in the image would then contain:

"RepoTags": ["myApp:1.2.3"]

but it actually shows:

"RepoTags": null

Am I assuming something wrong here or how should an image be tagged?

gesellix commented 10 months ago

Something like this works for me:

import de.gesellix.gradle.docker.tasks.DockerBuildTask

tasks {
  register<DockerBuildTask>("buildImage") {
    imageName.set("example:with-a-tag")
    buildContextDirectory.set(file("./docker/"))
  }
}
# docker images | grep a-tag
example                                         with-a-tag            3a15c35bf573   14 seconds ago   11.6MB

# docker inspect example:with-a-tag
[
    {
        "Id": "sha256:3a15c35bf573a59d31b08179b100ba92dc40adabe9b7796b7199d27bb92356f0",
        "RepoTags": [
            "example:with-a-tag"
        ],
        "RepoDigests": [
            "example@sha256:3a15c35bf573a59d31b08179b100ba92dc40adabe9b7796b7199d27bb92356f0"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2023-11-23T20:15:07.698857148Z",
  ...
]

I suppose there are other steps in your build script, which might cause the issue with missing tags - maybe a docker rmi equivalent?

antimatter84 commented 10 months ago

I can reproduce your example by running docker inspect and it shows the RepoTags correctly. I think, this is because the plugin probably loads the built image in my local docker registry and tags it. (I'm not that familiar with docker yet.)

The saved *.tar file does not contain the tag in the manifest file. I have to give you more information. The full build step:

val buildImage = tasks.register<DockerBuildTask>("buildAppImage") {
    dependsOn(copyAppResources) // copies stuff to build/app

    imageName.set("myApp:${project.version}")
    buildContextDirectory.set(file("build/app")) 

    val outputFilename = "myapp-${project.version}.tar"
    outputs.file(layout.buildDirectory.file(outputFilename))

    doLast {
        val engineResponse = dockerClient.save(listOf(imageId))
        FileOutputStream(layout.buildDirectory.file(outputFilename).get().asFile).use { 
            outputStream -> engineResponse.content.copyTo(outputStream)
        }
    }
}

The doLast action saves the image as tar file to disk but won't write the tag into the manifest file. Can this be done?

gesellix commented 10 months ago

Do you plan to upload (push) the final image to a Docker registry? I would expect that you use the docker push command, so that you would not have to work with .tar files manually. The plugin provides a DockerPushTask for that use case. That said: you would have to tag the image matching the registry address. In case of the official Docker Hub the example above would work, because some default will be used. When using a local Docker registry, you should use a tag like this: localhost:5000/myApp:version. This is required for the docker push command to connect to the local registry at localhost:5000. The plugin also allows to set the target registry independently.

The example might look like this:

tasks {
  val buildImage = register<DockerBuildTask>("buildImage") {
    imageName.set("myApp:${project.version}")
    buildContextDirectory.set(file("build/app"))
  }

  val pushImage = register<DockerPushTask>("pushImage") {
    dependsOn(buildImage)
    repositoryName.set("myApp:${project.version}")
    registry.set("localhost:5000")
  }
}
antimatter84 commented 9 months ago

Thanks for the suggestion. We could do it this way.

For the case here in question, I can pass the image name instead of the ID. Then the tag will be included in the *.tar files manifest.

dockerClient.save(listOf(imageName.get()))