com.bmuschko.gradle.docker.DockerSpringBootApplicationPlugin.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-docker-plugin Show documentation
Show all versions of gradle-docker-plugin Show documentation
Gradle plugin for managing Docker images and containers.
package com.bmuschko.gradle.docker
import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage
import com.bmuschko.gradle.docker.tasks.image.DockerPushImage
import com.bmuschko.gradle.docker.tasks.image.Dockerfile
import groovy.transform.CompileStatic
import org.gradle.api.Action
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.CopySpec
import org.gradle.api.plugins.ExtensionAware
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.Sync
import org.springframework.boot.loader.tools.MainClassFinder
import java.util.concurrent.Callable
import static com.bmuschko.gradle.docker.utils.ConventionPluginHelper.getMainJavaSourceSetOutput
import static com.bmuschko.gradle.docker.utils.ConventionPluginHelper.getRuntimeClasspathConfiguration
/**
* @since 3.4.5
*/
@CompileStatic
class DockerSpringBootApplicationPlugin implements Plugin {
public static final String SPRING_BOOT_APPLICATION_EXTENSION_NAME = 'springBootApplication'
public static final String SYNC_BUILD_CONTEXT_TASK_NAME = 'dockerSyncBuildContext'
public static final String DOCKERFILE_TASK_NAME = 'dockerCreateDockerfile'
public static final String BUILD_IMAGE_TASK_NAME = 'dockerBuildImage'
public static final String PUSH_IMAGE_TASK_NAME = 'dockerPushImage'
@Override
void apply(Project project) {
project.plugins.apply(DockerRemoteApiPlugin)
DockerExtension dockerExtension = project.extensions.getByType(DockerExtension)
DockerSpringBootApplication dockerSpringBootApplication = configureExtension(project, dockerExtension)
project.plugins.withType(JavaPlugin) {
project.plugins.withId('org.springframework.boot') {
Dockerfile createDockerfileTask = createDockerfileTask(project, dockerSpringBootApplication)
Sync syncBuildContextTask = createSyncBuildContextTask(project, createDockerfileTask)
createDockerfileTask.dependsOn syncBuildContextTask
DockerBuildImage dockerBuildImageTask = createBuildImageTask(project, createDockerfileTask, dockerSpringBootApplication)
createPushImageTask(project, dockerBuildImageTask)
}
}
}
private static DockerSpringBootApplication configureExtension(Project project, DockerExtension dockerExtension) {
((ExtensionAware) dockerExtension).extensions.create(SPRING_BOOT_APPLICATION_EXTENSION_NAME, DockerSpringBootApplication, project)
}
private static Sync createSyncBuildContextTask(Project project, Dockerfile createDockerfileTask) {
project.tasks.create(SYNC_BUILD_CONTEXT_TASK_NAME, Sync, new Action() {
@Override
void execute(Sync sync) {
sync.with {
group = DockerRemoteApiPlugin.DEFAULT_TASK_GROUP
description = "Copies the distribution resources to a temporary directory for image creation."
dependsOn project.tasks.getByName(JavaPlugin.CLASSES_TASK_NAME)
into(createDockerfileTask.destDir)
into('libs', new Action() {
@Override
void execute(CopySpec copySpec) {
copySpec.from(getRuntimeClasspathConfiguration(project))
}
})
into('resources', new Action() {
@Override
void execute(CopySpec copySpec) {
copySpec.from(getMainJavaSourceSetOutput(project).resourcesDir)
}
})
into('classes', new Action() {
@Override
void execute(CopySpec copySpec) {
copySpec.from(getMainJavaSourceSetOutput(project).classesDirs)
}
})
}
}
})
}
private static Dockerfile createDockerfileTask(Project project, DockerSpringBootApplication dockerSpringBootApplication) {
project.tasks.create(DOCKERFILE_TASK_NAME, Dockerfile, new Action() {
@Override
void execute(Dockerfile dockerfile) {
dockerfile.with {
description = 'Creates the Docker image for the Spring Boot application.'
from(project.provider(new Callable() {
@Override
Dockerfile.From call() throws Exception {
new Dockerfile.From(dockerSpringBootApplication.baseImage.get())
}
}))
workingDir('/app')
copyFile(project.provider(new Callable() {
@Override
Dockerfile.File call() throws Exception {
if (new File(dockerfile.destDir.get().asFile, 'libs').isDirectory()) {
return new Dockerfile.File('libs', 'libs/')
}
}
}))
copyFile(project.provider(new Callable() {
@Override
Dockerfile.File call() throws Exception {
if (getMainJavaSourceSetOutput(project).resourcesDir.isDirectory()) {
return new Dockerfile.File('resources', 'resources/')
}
}
}))
copyFile('classes', 'classes/')
entryPoint(project.provider(new Callable>() {
@Override
List call() throws Exception {
["java", "-cp", "/app/resources:/app/classes:/app/libs/*", getSpringApplicationMainClassName(project)]
}
}))
exposePort(dockerSpringBootApplication.ports)
}
}
})
}
private static DockerBuildImage createBuildImageTask(Project project, Dockerfile createDockerfileTask, DockerSpringBootApplication dockerSpringBootApplication) {
project.tasks.create(BUILD_IMAGE_TASK_NAME, DockerBuildImage, new Action() {
@Override
void execute(DockerBuildImage dockerBuildImage) {
dockerBuildImage.with {
description = 'Builds the Docker image for the Spring Boot application.'
dependsOn createDockerfileTask
tags.add(determineImageTag(project, dockerSpringBootApplication))
}
}
})
}
private static Provider determineImageTag(Project project, DockerSpringBootApplication dockerSpringBootApplication) {
project.provider(new Callable() {
@Override
String call() throws Exception {
if (dockerSpringBootApplication.tag.getOrNull()) {
return dockerSpringBootApplication.tag.get()
}
String tagVersion = project.version == 'unspecified' ? 'latest' : project.version
String artifactAndVersion = "${project.name}:${tagVersion}".toLowerCase().toString()
project.group ? "$project.group/$artifactAndVersion".toString() : artifactAndVersion
}
})
}
private static void createPushImageTask(Project project, DockerBuildImage dockerBuildImageTask) {
project.tasks.create(PUSH_IMAGE_TASK_NAME, DockerPushImage, new Action() {
@Override
void execute(DockerPushImage dockerPushImage) {
dockerPushImage.with {
description = 'Pushes created Docker image to the repository.'
dependsOn dockerBuildImageTask
imageName.set(project.provider(new Callable() {
@Override
String call() throws Exception {
dockerBuildImageTask.getTags().get().first() as String
}
}))
}
}
})
}
private static String getSpringApplicationMainClassName(Project project) {
for (File classesDir : getMainJavaSourceSetOutput(project).classesDirs) {
String mainClassName = MainClassFinder.findSingleMainClass(classesDir, 'org.springframework.boot.autoconfigure.SpringBootApplication')
if (mainClassName) {
return mainClassName
}
}
throw new IllegalStateException('Main class name could not be resolved')
}
}