gradle-docker-plugin: Applying multiple tags to created image fails with NullPointerException

I’m trying to apply multiple tags to an image created with a DockerCreateImage task. As the DockerTagImage task only supports a single tag, I’m creating tagging tasks on the fly in my gradle build based on the configured tags (basically a comma separated list):

build.gradle:

apply from: "${project.rootDir}/gradle/docker-utils.gradle"
...
task createImage(type: DockerBuildImage) {
  inputDir = file('src/main/docker')
  tag = dockerProps['name']
}

//task tagImage(type: DockerTagImage) {
//  targetImageId { createImage.getImageId() }
//  repository = dockerProps['name']
//  tag = dockerProps['tags'].split(',')[0]
//}
task tagImage << {
  tagDockerImage(createImage.getImageId(), dockerProps['name'], dockerProps['tags'].split(','))
}
tasks.createImage.finalizedBy(tagImage)

docker-utils.gradle:

buildscript {
  repositories { mavenCentral() }

  dependencies {
    classpath group: 'com.bmuschko', name: 'gradle-docker-plugin', version: '2.6.8'
  }
}
import com.bmuschko.gradle.docker.tasks.image.DockerTagImage

def tagDockerImage(String aImageId, String aName, String[] aTags) {

  def i = 0
  aTags.each { tagIt ->
    def tagTask = tasks.create(name: "tagDockerImage${i}", type: DockerTagImage) {
      targetImageId { aImageId }
      repository = aName.trim()
      tag = tagIt.trim()
    }

    tagTask.doFirst { logger.info "Tagging image '${imageId}' with tag '${repository}:${tag}'" }

    tagTask.execute()
    i++
  }
}

// Export methods by turning them into closures
ext { tagDockerImage = this.&tagDockerImage }

This works fine in a single project build but in a multi-project built I’m getting a NullPointerException:

Script 'C:\ws\gradle\docker-utils.gradle' line: 23

* What went wrong:
Execution failed for task ':docker-build:tagDockerImage0'.
> Cannot invoke method withClasspath() on null object

* Try:
Run with --info or --debug option to get more log output.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':docker-build:tagDockerImage0'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.AbstractTask.execute(AbstractTask.java:305)
        at org.gradle.api.internal.TaskInternal$execute$0.call(Unknown Source)
        at docker_utils_xgqqku9s19rhgyrizdsi68vr$_tagDockerImage_closure2.doCall(C:\ws\AXC_DEFAULT_1\ng\gradle\docker-utils.gradle:26)
        at docker_utils_xgqqku9s19rhgyrizdsi68vr.tagDockerImage(C:\ws\AXC_DEFAULT_1\ng\gradle\docker-utils.gradle:17)
        at org.gradle.api.internal.CompositeDynamicObject.invokeMethod(CompositeDynamicObject.java:159)
        at org.gradle.groovy.scripts.BasicScript.methodMissing(BasicScript.java:79)
        at axcng_docker_build_56wjd78akrg79ut9ugohy4zrb$_run_closure3.doCall(C:\ws\AXC_DEFAULT_1\ng\axcng-docker-build\axcng-docker-build.gradle:27)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:554)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:535)
        at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:77)
        at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:73)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: java.lang.NullPointerException: Cannot invoke method withClasspath() on null object
        at com.bmuschko.gradle.docker.tasks.AbstractDockerRemoteApiTask.runInDockerClassPath(AbstractDockerRemoteApiTask.groovy:62)
        at com.bmuschko.gradle.docker.tasks.AbstractDockerRemoteApiTask$runInDockerClassPath.callCurrent(Unknown Source)
        at com.bmuschko.gradle.docker.tasks.AbstractDockerRemoteApiTask.start(AbstractDockerRemoteApiTask.groovy:56)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:227)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:220)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:209)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:585)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:568)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        ... 35 more

I just noticed that it works as well, if I put the tagDockerImage function directly into the build.gradle file of the docker project, instead of importing it from another gradle file by apply from. This is however not the desired solution as I have multiple docker sub-projects in this setup and I don’t like to copy & paste this function to each of the projects…

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 25 (2 by maintainers)

Most upvoted comments

There is a supported, simpler way of doing this now. See the example I posted to this repository’s wiki here.

@cdancy thanks for the update. Hopefully updating to Gradle 3.0.0 will not be much of an effort, once it is released…

@dpr-rec it was introduced in 3.0.8 (see RELEASE_NOTES)

It was my pleasure. I am likely to use it myself quite a bit. I like to keep the documentation as close to the source as practical.

Ok, I played around a little bit and this problem doesn’t seem to be specifically related to the com.github.jengelman.gradle.plugins:gradle-processes:0.3.0 plugin, but to the buildscript dependencies in general. In our real-life project we have multiple buildscript dependencies (11 in total). To make the imported gradle file working, I needed to add all of these dependencies to the imported file in exactly the same order as in the root build.gradle file.