Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encounters error if imageId file exists, and the image it's referring is already built ("repoTags" is null) #1227

Open
nvilagos opened this issue Nov 29, 2024 · 1 comment

Comments

@nvilagos
Copy link

Expected Behavior

DockerBuildImage should be able to successfully finish the build Docker image task.

Current Behavior

DockerBuildImage fails the build Docker image task if the image is already built previously and the following file exists: build/.docker/docker_buildImage-imageId.txt.

The error message is the following:

Cannot invoke "java.util.List.containsAll(java.util.Collection)" because "repoTags" is null

gradle-docker-plugin-evidence-01

gradle-docker-plugin-evidence-02

gradle-docker-plugin-evidence-03

gradle-docker-plugin-evidence-04

gradle-docker-plugin-evidence-05

gradle-docker-plugin-evidence-06

Context

I want to build a Docker image as a Gradle task so I can use it in a later task.

Steps to Reproduce (for bugs)

  1. Run the Docker build for the first time.
  2. Keep intact the generated files and images.
  3. Run the Docker build again to make it fail.

Your Environment

Gradle Docker plugin artifact: com.bmuschko.docker-remote-api:9.4.0
Gradle version: 8.11.1
OS: Windows 11

Possible workaround

Before every Docker image build, delete either the previously built Docker image, or the following file: build/.docker/docker_buildImage-imageId.txt.

@nvilagos nvilagos changed the title Encounters error if imageId file exists, but the image it's referring is already built ("repoTags" is null) Encounters error if imageId file exists, and the image it's referring is already built ("repoTags" is null) Nov 29, 2024
@jGleitz
Copy link

jGleitz commented Dec 1, 2024

Root Cause Analysis

I found the root cause of this issue, which is docker-remote-api packaging some of its dependencies but not renaming the packages of all of them. This leads to very difficult-to-debug behaviour:

  1. docker-remote-api is shading (i.e. including in the .jar and renaming the packages of) jackson-api and jackson-databind, but is including docker-java-api and docker-java-core in the .jar without renaming the packages. Because of this, docker-remote-api puts the classes of those two docker-java dependencies on the classpath (with their original package names!), but all jackson references—for example the @JsonProperty annotations—in those class files link to com.bmuschko.gradle.docker.shaded.com.fasterxml.jackson.….
  2. We added another dependency to our build (testcontainers, specifically) that depends on docker-java-api. This dependency brought the classes of docker-java-api to the classpath, replacing the classes packaged in docker-remote-api. However, the dependency did not replace docker-java-core.
  3. With this setup, docker-remote-api invoked its version of docker-java-core, which, through its com.bmuschko.gradle.docker.shaded.com.fasterxml.jackson.databind.ObjectMapper, searched for com.bmuschko.gradle.docker.shaded.com.fasterxml.jackson.annotation.JsonProperty annotations. However, the normal version of docker-java-api on our classpath had, of course, com.fasterxml.jackson.annotation.JsonProperty annotations. This caused deserialization to fail and some properties to be null. Amazingly, this was only an issue when docker-remote-api tried to check a pre-existing image. Hence, the workaround of removing the build/.docker directory fixed all issues we were facing.

To illustrate the problem, here is the decompiled com.github.dockerjava.api.command.InspectImageResponse, as it is included in the .jar of docker-remote-api. Notice how InspectImageResponse has the normal package of docker-java-api, but references the renamed versions of jackson-api:
grafik

Improved Workaround

In our case, adding a dependency on docker-java-core to our buildSrc project fixes the issue. With that dependency on the classpath, all references to the shaded version of Jackson are replaced:

implementation(platform("com.github.docker-java:docker-java-bom:3.4.0"))
implementation("com.github.docker-java:docker-java-core")

However, this effectively disables the shading done in gradle-docker-plugin, which, I assume, exists for a reason.

Proposed fix

gradle-docker-plugin should either shade all its dependencies correctly (i.e. package and rename them), or not shade any of them. Including a dependency with its original package name but different compiled code will always lead to weird dependency errors when another dependency brings in docker-java. At the very least, other dependencies can effectively disable the shading, which defeats its purpose.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants