1. Introduction

Gradle plugin for managing Docker images and containers using via its remote API. The heavy lifting of communicating with the Docker remote API is handled by the Docker Java library. Please refer to the library’s documentation for more information on the supported Docker’s client API and Docker server version.

This plugin requires Gradle >= 4.8 to work properly.

1.1. Benefits

There are various benefits for using this plugin:

  1. Seamless integration with the build tool Gradle and its DSL.

  2. Handles complicated communication logic between Docker client and daemon under the covers.

  3. Simplifies the definition of complex workflows.

  4. Minimizes build script setup logic by providing sensible conventions for different use cases.

1.2. Limitations

The functionality of the plugin does not cover all possible use cases. Be aware of the following limitations:

  • A task type may not provide all possible options for the underlying Docker operation. Open an issue if you feel like it should be supported.

  • You cannot build multi-container applications via Docker Compose. The Avast Docker Compose plugin has proven to be a capable alternative.

  • Managing a Docker Swarm and/or Stack is not supported.

1.4. Provided Plugins

The binary distribution is available on the Gradle plugin portal, Bintray’s JCenter and Maven Central. It contains the following plugins:

Plugin Id Automatically applies Type Description

com.bmuschko.docker-remote-api

-

DockerRemoteApiPlugin

Provides custom tasks for interacting with Docker via its remote API.

com.bmuschko.docker-java-application

com.bmuschko.docker-remote-api

DockerJavaApplicationPlugin

Creates and pushes a Docker image for a Java application.

com.bmuschko.docker-spring-boot-application

com.bmuschko.docker-remote-api

DockerSpringBootApplicationPlugin

Creates and pushes a Docker image for a Spring Boot application.

Which plugin you chose in your project entirely depends on the use case you want to fulfill. Refer to the relevant portions of the user guide that describe the purpose and usage of each plugin in more detail.

1.5. Getting Started

The plugin can be applied with the buildscript syntax or the plugin DSL. Let’s say you’d want to go with the plugin that provides the plain Docker operations for managing Docker images and containers. See the Gradle user guide for more information on applying plugins.

1.5.1. Applying the Plugin Using the buildscript Syntax

Groovy
buildscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath 'com.bmuschko:gradle-docker-plugin:{project-version}'
    }
}

apply plugin: 'com.bmuschko.docker-remote-api'
Kotlin
buildscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath("com.bmuschko:gradle-docker-plugin:{project-version}")
    }
}

apply(plugin = "com.bmuschko.docker-remote-api")

1.5.2. Applying the Plugin Using the Plugin DSL

Groovy
plugins {
    id 'com.bmuschko.docker-remote-api' version '{project-version}'
}
Kotlin
plugins {
    id("com.bmuschko.docker-remote-api") version "{project-version}"
}

1.5.3. Applying the Plugin From a Script Plugin

Applying the plugin from a script plugin requires the use of the fully-qualified class name due to a bug in Gradle core. Be aware that the plugin DSL cannot be used to apply a binary plugin from a script plugin.

When used with the Kotlin DSL, it is recommended to move your implementation into the buildSrc project.
gradle/docker.gradle
buildscript {
    repositories {
        gradlePluginPortal()
    }
    dependencies {
        classpath 'com.bmuschko:gradle-docker-plugin:{project-version}'
    }
}

apply plugin: com.bmuschko.gradle.docker.DockerRemoteApiPlugin
build.gradle
apply from: 'gradle/docker.gradle'

2. Remote API Plugin

The plugin com.bmuschko.docker-remote-api allows for interacting with Docker via its remote API. You can model any workflow imaginable by creating enhanced task of the custom task provided by the plugin.

2.1. Usage

Groovy
plugins {
    id 'com.bmuschko.docker-remote-api' version '{project-version}'
}

// Import task types
import com.bmuschko.gradle.docker.tasks.image.*

// Use task types
task buildMyAppImage(type: DockerBuildImage) {
    inputDir = file('docker/myapp')
    tag = 'test/myapp:latest'
}
Kotlin
plugins {
    id("com.bmuschko.docker-remote-api") version "{project-version}"
}

// Import task types
import com.bmuschko.gradle.docker.tasks.image.*

// Use task types
tasks.create("buildMyAppImage", DockerBuildImage::class) {
    inputDir.set(file("docker/myapp"))
    tag.set("test/myapp:latest")
}

The plugin automatically resolves the Docker Java library with the pre-configured version under the covers. The only configuration you will have to provide in your build script is the repository hosting the library and its transitive dependencies. One repository that hosts them all is Maven Central.

Groovy
repositories {
    mavenCentral()
}
Kotlin
repositories {
    mavenCentral()
}

2.2. Extension

The plugin defines an extension with the namespace docker. The following properties can be configured:

Property name Type Default value Description

url

Property<String>

see below

The server URL to connect to via Docker’s remote API.

certPath

DirectoryProperty

null

The path to certificates for communicating with Docker over SSL.

apiVersion

Property<String>

null

The remote API version. For most cases this can be left null.

The default value is now generated based on a best guess attempt given the operating system and environment:

Operating system Value

Unix-based machine

unix:///var/run/docker.sock

Windows-based machine (and everything else)

tcp://127.0.0.1:2375

Image pull or push operations against the public Docker Hub registry or a private registry may require authentication. You can provide those credentials in the registryCredentials closure:

Property name Type Default value Description

url

Property<String>

https://index.docker.io/v1/

The registry URL.

username

Property<String>

null

The registry username.

password

Property<String>

null

The registry password.

email

Property<String>

null

The registry email address.

2.2.1. Working With a TLS-enabled Docker Instance

Starting with Docker version 1.3, TLS is enabled by default. Please consult the Docker documentation "Protect the Docker daemon socket" to set up your certificate. The following example demonstrates how to configure the plugin to use those certificates. Additionally, this code snippet shows how to set the user credentials.

Groovy
docker {
    url = 'https://192.168.59.103:2376'
    certPath = new File(System.properties['user.home'], '.boot2docker/certs/boot2docker-vm')

    registryCredentials {
        url = 'https://index.docker.io/v1/'
        username = 'bmuschko'
        password = 'pwd'
        email = 'benjamin.muschko@gmail.com'
    }
}
Kotlin
docker {
    url.set("https://192.168.59.103:2376")
    certPath.set(File(System.getProperty("user.home"), ".boot2docker/certs/boot2docker-vm"))

    registryCredentials {
        url.set("https://index.docker.io/v1/")
        username.set("bmuschko")
        password.set("pwd")
        email.set("benjamin.muschko@gmail.com")
    }
}

2.2.2. Working With Google Cloud And Using a Key File

Groovy
docker {
    registryCredentials {
        url = 'https://gcr.io'
        username = '_json_key'
        password = file('keyfile.json').text
    }
}
Kotlin
docker {
    registryCredentials {
        url.set("https://gcr.io")
        username.set("_json_key")
        password.set(file("keyfile.json").readText())
    }
}

2.2.3. Working With a Docker Instance Without TLS

The following example assumes that you disabled TLS on your Docker instance. You can do so by setting DOCKER_TLS=no in the file /var/lib/boot2docker/profile.

Groovy
docker {
    url = 'tcp://192.168.59.103:2375'
}
Kotlin
docker {
    url.set("tcp://192.168.59.103:2375")
}

On Unix the Docker daemon listens by default on unix:///var/run/docker.sock.

On Windows the Docker daemon listens by default on npipe:////./pipe/docker_engine though this is not currently supported. We instead fall back to tcp://127.0.0.1:2375.

2.3. Custom task types

2.3.1. Misc

The plugin provides the following general-purpose custom task types:

Type Description

DockerClient

Passes the raw docker-java client to the onNext closure if it’s defined.

DockerInfo

Displays system-wide information.

DockerVersion

Show the docker version information.

2.3.2. Images

The plugin provides the following custom task types for managing images:

Type Description

Dockerfile

Creates a Dockerfile based on the provided instructions.

DockerBuildImage

Builds an image from a Dockerfile.

DockerCommitImage

Creates a new image from a container’s changes.

DockerInspectImage

Returns low-level information on the image.

DockerListImages

Lists images in registry.

DockerPullImage

Pulls an image from the registry.

DockerPushImage

Pushes an image to a registry.

DockerRemoveImage

Removes an image from the filesystem.

DockerTagImage

Tags an image in registry.

DockerSaveImage

Saves an image to file.

DockerLoadImage

Loads an image from file.

2.3.3. Containers

The plugin provides the following custom task types for managing containers:

Type Description

DockerCopyFileToContainer

Copies a path from the host into the container.

DockerCopyFileFromContainer

Copies a path from the container as a tar file on to the host.

DockerCreateContainer

Creates a container.

DockerInspectContainer

Returns low-level information on the container.

DockerKillContainer

Kills the container for a given id.

DockerRemoveContainer

Removes the container for a given id from the filesystem.

DockerRenameContainer

Rename a container.

DockerRestartContainer

Restarts the container for a given id.

DockerStartContainer

Starts the container for a given id.

DockerStopContainer

Stops the container for a given id.

DockerWaitContainer

Blocks until container for a given id stops.

DockerLogsContainer

Copies the container output to the Gradle process standard out/err.

DockerExecContainer

Executes a command within a running container.

DockerInspectExecContainer

Inspects task executed inside container with DockerExecContainer command.

2.3.4. Networks

The plugin provides the following custom task types for managing networks:

Type Description

DockerCreateNetwork

Creates a network.

DockerInspectNetwork

Returns low-level information on the network.

DockerRemoveNetwork

Removes the network.

2.3.5. Extras

The plugin provides the following additional tasks:

Type Description

DockerExecStopContainer

Shut down container with cmd, polling for it to enter a non-running state, and if that does not succeed in time issue stop request.

DockerLivenessContainer

Polls an arbitrary containers logs for a message indicating liveness.

DockerWaitHealthyContainer

Blocks until the container for a given id becomes healthy.

2.4. Reactive Streams

As needed, we will implement reactive methods as described in reactive-streams. We implement these here as optional closures for all tasks. Currently the only supported methods are onError, onNext, onComplete. Various examples on how to use these can be found in our reactive tests.

2.4.1. Reacting to an Error

The onError closure is passed the exception that is thrown for you to handle. If you silently ignore we will not throw the exception behind the scenes. The below example is a common use-case that arises when someone wants to remove a container whether it exists or not but does not want to fail hard.

Groovy
task removeContainer1(type: DockerRemoveContainer) {
    targetContainerId 'container-that-does-not-exist'
    onError { exception ->
        // Ignore exception if container does not exist otherwise throw it
        if (!exception.message.contains('No such container'))
            throw exception
    }
}
Kotlin
tasks.create("removeContainer1", DockerRemoveContainer::class) {
    targetContainerId("container-that-does-not-exist")
    onError {
        // Ignore exception if container does not exist otherwise throw it
        if (!this.message!!.contains("No such container"))
            throw this
    }
}

2.4.2. Reacting to Data Returned by an Operation

The onNext closure is passed the next iterative response upon execution. For all other tasks we simply hand you back the object that is given to us by docker-java which is a pojo representation of the json handed back by docker. Thus, and much like the onError closure, all delegation is now in your control. Any properties/values expected to be set will not be done unless you do them.

Iterative tasks are things like DockerBuildImage, DockerLogsContainer, DockerListImages. These tasks have output which can be iterated over. The example below demonstrates how we iterate over each log message passing that to the closure for the user to work on.

Groovy
task logContainer(type: DockerLogsContainer) {
    targetContainerId 'container-that-does-exist'
    follow = true
    tailAll = true
    onNext { message ->
        // Each log message from the container will be passed as it's made available
        logger.quiet message.toString()
    }
}
Kotlin
tasks.create("logContainer", DockerLogsContainer::class) {
    targetContainerId("container-that-does-not-exist")
    follow.set(true)
    tailAll.set(true)
    onNext {
        // Each log message from the container will be passed as it's made available
        logger.quiet(this.toString())
    }
}

2.4.3. Reacting to the Completion of an Operation

The onComplete closure is not passed anything upon execution. It works in the same fashion that doLast does but is instead part of this task and thus executes before doLast does. This closure executes only upon success. The below example demonstrates how this works.

Groovy
task removeContainer2(type: DockerRemoveContainer) {
    targetContainerId 'container-that-does-exist'
    onComplete {
        println 'Executes first'
    }
    doLast {
        println 'Executes second'
    }
}
Kotlin
tasks.create("removeContainer2", DockerRemoveContainer::class) {
    targetContainerId("container-that-does-exist")
    onComplete {
        println("Executes first")
    }
    doLast {
        println("Executes second")
    }
}

2.5. Examples

The following usage examples demonstrate code for common use cases. More scenarios can be found in the functional tests.

2.5.1. Creating a Dockerfile And Building an Image

A Dockerfile can be created by the Dockerfile custom tasks. The Dockerfile instructions need to be declare in the correct order.

Groovy
plugins {
    id 'com.bmuschko.docker-remote-api' version '{project-version}'
}

import com.bmuschko.gradle.docker.tasks.image.Dockerfile
import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage

task createDockerfile(type: Dockerfile) {
    destFile = project.file('build/mydockerfile/Dockerfile')
    from 'ubuntu:12.04'
    label(['maintainer': 'Benjamin Muschko "benjamin.muschko@gmail.com"'])
}

task buildImage(type: DockerBuildImage) {
    dependsOn createDockerfile
    inputDir = createDockerfile.destFile.get().asFile.parentFile
    tag = 'bmuschko/myimage:latest'
}
Kotlin
plugins {
    id("com.bmuschko.docker-remote-api") version "{project-version}"
}

import com.bmuschko.gradle.docker.tasks.image.Dockerfile
import com.bmuschko.gradle.docker.tasks.image.DockerBuildImage

val createDockerfile by tasks.creating(Dockerfile::class) {
    destFile.set(file("build/mydockerfile/Dockerfile"))
    from("ubuntu:12.04")
    label(mapOf("maintainer" to "Benjamin Muschko 'benjamin.muschko@gmail.com'"))
}

tasks.create("buildImage", DockerBuildImage::class) {
    dependsOn(createDockerfile)
    inputDir.set(createDockerfile.getDestFile().get().asFile.parentFile)
    tag.set("bmuschko/myimage:latest")
}

2.5.2. Executing Functional Tests Against a Running Container

The following example code demonstrates how to build a Docker image from a Dockerfile, starts up a container for this image and exercises functional tests against the running container. At the end of this operation, the container is stopped.

Groovy
plugins {
    id 'com.bmuschko.docker-remote-api' version '{project-version}'
}

import com.bmuschko.gradle.docker.tasks.container.*
import com.bmuschko.gradle.docker.tasks.image.*

task buildMyAppImage(type: DockerBuildImage) {
    inputDir = file('docker/myapp')
    tag = 'test/myapp:latest'
}

task createMyAppContainer(type: DockerCreateContainer) {
    dependsOn buildMyAppImage
    targetImageId buildMyAppImage.getImageId()
    portBindings = ['8080:8080']
    autoRemove = true
}

task startMyAppContainer(type: DockerStartContainer) {
    dependsOn createMyAppContainer
    targetContainerId createMyAppContainer.getContainerId()
}

task stopMyAppContainer(type: DockerStopContainer) {
    targetContainerId createMyAppContainer.getContainerId()
}

task functionalTestMyApp(type: Test) {
    dependsOn startMyAppContainer
    finalizedBy stopMyAppContainer
}
Kotlin
plugins {
    id("com.bmuschko.docker-remote-api") version "{project-version}"
}

import com.bmuschko.gradle.docker.tasks.container.*
import com.bmuschko.gradle.docker.tasks.image.*

val buildMyAppImage by tasks.creating(DockerBuildImage::class) {
    inputDir.set(file("docker/myapp"))
    tag.set("test/myapp:latest")
}

val createMyAppContainer by tasks.creating(DockerCreateContainer::class) {
    dependsOn(buildMyAppImage)
    targetImageId(buildMyAppImage.getImageId())
    portBindings.set(listOf("8080:8080"))
    autoRemove.set(true)
}

val startMyAppContainer by tasks.creating(DockerStartContainer::class) {
    dependsOn(createMyAppContainer)
    targetContainerId(createMyAppContainer.getContainerId())
}

val stopMyAppContainer by tasks.creating(DockerStopContainer::class) {
    targetContainerId(createMyAppContainer.getContainerId())
}

tasks.create("functionalTestMyApp", Test::class) {
    dependsOn(startMyAppContainer)
    finalizedBy(stopMyAppContainer)
}

2.5.3. Linking With Other Containers

In many situations your container does not start without dependencies like database. In that case you may wish using traditional linking:

Groovy
plugins {
    id 'com.bmuschko.docker-remote-api' version '{project-version}'
}

import com.bmuschko.gradle.docker.tasks.container.*
import com.bmuschko.gradle.docker.tasks.image.*

task buildMyAppImage(type: DockerBuildImage) {
    inputDir = file('docker/myapp')
    tag = 'test/myapp'
}

task createDBContainer(type: DockerCreateContainer) {
    targetImageId 'postgres:latest'
    containerName = 'docker_auto'
    autoRemove = true
}

task createMyAppContainer(type: DockerCreateContainer) {
    dependsOn buildMyAppImage, createDBContainer
    targetImageId buildMyAppImage.getImageId()
    portBindings = ['8080:8080']
    autoRemove = true

    // doFirst required! #319
    doFirst{
        // `database` there will be host used by application to DB connect
        links = [ "${createDBContainer.getContainerId().get()}:database" ]
    }

    // If you use Systemd in containers you should also add lines. #320
    binds = [ '/sys/fs/cgroup': '/sys/fs/cgroup' ]
    tty = true
}

task startMyAppContainer(type: DockerStartContainer) {
    dependsOn createMyAppContainer
    targetContainerId createMyAppContainer.getContainerId()
}

task stopMyAppContainer(type: DockerStopContainer) {
    targetContainerId createMyAppContainer.getContainerId()
}

task functionalTestMyApp(type: Test) {
    dependsOn startMyAppContainer
    finalizedBy stopMyAppContainer
}
Kotlin
plugins {
    id("com.bmuschko.docker-remote-api") version "{project-version}"
}

import com.bmuschko.gradle.docker.tasks.container.*
import com.bmuschko.gradle.docker.tasks.image.*

val buildMyAppImage by tasks.creating(DockerBuildImage::class) {
    inputDir.set(file("docker/myapp"))
    tag.set("test/myapp")
}

val createDBContainer by tasks.creating(DockerCreateContainer::class) {
    targetImageId("postgres:latest")
    containerName.set("docker_auto")
    autoRemove.set(true)
}

val createMyAppContainer by tasks.creating(DockerCreateContainer::class) {
    dependsOn(buildMyAppImage, createDBContainer)
    targetImageId(buildMyAppImage.getImageId())
    portBindings.set(listOf("8080:8080"))
    autoRemove.set(true)

    // doFirst required! #319
    doFirst {
        // `database` there will be host used by application to DB connect
        links.set(listOf("${createDBContainer.getContainerId().get()}:database"))
    }

    // If you use Systemd in containers you should also add lines. #320
    binds.set(mapOf("/sys/fs/cgroup" to "/sys/fs/cgroup"))
    tty.set(true)
}

val startMyAppContainer by tasks.creating(DockerStartContainer::class) {
    dependsOn(createMyAppContainer)
    targetContainerId(createMyAppContainer.getContainerId())
}

val stopMyAppContainer by tasks.creating(DockerStopContainer::class) {
    targetContainerId(createMyAppContainer.getContainerId())
}

tasks.create("functionalTestMyApp", Test::class) {
    dependsOn(startMyAppContainer)
    finalizedBy(stopMyAppContainer)
}

3. Java Application Plugin

The plugin com.bmuschko.docker-java-application is a highly opinionated plugin for projects applying the application plugin. Under the covers the plugin preconfigures tasks for creating and pushing Docker images for your Java application. The default configuration is tweakable via an exposed extension.

3.1. Usage

Groovy
plugins {
    id 'java'
    id 'application'
    id 'com.bmuschko.docker-java-application' version '{project-version}'
}
Kotlin
plugins {
    java
    application
    id("com.bmuschko.docker-java-application") version "{project-version}"
}

3.2. Extension

The plugin defines an extension with the namespace javaApplication as a child of the docker namespace. The following properties can be configured:

Property name Type Default value Description

baseImage

Property<String>

openjdk:jre-alpine

The Docker base image used for Java application.

exec

Action<CompositeExecInstruction>

Create ENTRYPOINT using script from Application plugin

The ENTRYPOINT and/or CMD Dockerfile instructions

ports

ListProperty<Integer>

[8080]

The Docker image exposed ports (if provided, this values will override port configuration property)

tag

Property<String>

<project.group>/<applicationName>:<project.version>

The tag used for the Docker image.

Groovy
docker {
    javaApplication {
        baseImage = 'dockerfile/java:openjdk-7-jre'
        maintainer = 'Benjamin Muschko "benjamin.muschko@gmail.com"'
        ports = [9090, 5701]
        tag = 'jettyapp:1.115'
    }
}
Kotlin
docker {
    javaApplication {
        baseImage.set("dockerfile/java:openjdk-7-jre")
        maintainer.set("Benjamin Muschko 'benjamin.muschko@gmail.com'")
        ports.set(listOf(9090, 5701))
        tag.set("jettyapp:1.115")
    }
}

3.2.1. Adding custom instructions to Dockerfile

The exec extension property accepts a Closure or Provider which delegates to the DockerJavaApplication.CompositeExecInstruction subset of the Dockerfile task. It allows for specifying custom ENTRYPOINT or CMD commands at an appropriate location in the Dockerfile.

Groovy
docker {
    javaApplication {
        exec {
            defaultCommand 'server'
            entryPoint 'myApp/bin/containerLaunch.sh'
        }
    }
}
Kotlin
docker {
    javaApplication {
        exec {
            defaultCommand("server")
            entryPoint("myApp/bin/containerLaunch.sh")
        }
    }
}

3.3. Tasks

The plugin provides a set of tasks for your project and preconfigures them with sensible defaults.

Task name Depends On Type Description

dockerCopyDistResources

distTar

Sync

Copies the resource files (like the Java application’s TAR file) to a temporary directory for image creation.

dockerDistTar

dockerCopyDistResources

Dockerfile

Creates the Docker image for the Java application.

dockerBuildImage

dockerDistTar

DockerBuildImage

Builds the Docker image for the Java application.

dockerPushImage

dockerBuildImage

DockerPushImage

Pushes created Docker image to the repository.

3.4. Examples

The following usage examples demonstrate code for common use cases. More scenarios can be found in the functional tests.

3.4.1. Using the Plugin for an Application Run on Jetty

Groovy
plugins {
    id 'java'
    id 'application'
    id 'com.bmuschko.docker-java-application' version '{project-version}'
}

version = '1.0'
sourceCompatibility = 1.7

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.eclipse.jetty.aggregate:jetty-all:9.2.5.v20141112'
}

mainClassName = 'com.bmuschko.gradle.docker.application.JettyMain'

docker {
    javaApplication {
        maintainer = 'Jon Doe "jon.doe@gmail.com"'
    }
}
Kotlin
plugins {
    java
    application
    id("com.bmuschko.docker-java-application") version "{project-version}"
}

version = "1.0"

java {
    sourceCompatibility = JavaVersion.VERSION_1_7
    targetCompatibility = JavaVersion.VERSION_1_7
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.eclipse.jetty.aggregate:jetty-all:9.2.5.v20141112")
}

application {
    mainClassName = "com.bmuschko.gradle.docker.application.JettyMain"
}

docker {
    javaApplication {
        maintainer.set("Jon Doe 'jon.doe@gmail.com'")
    }
}

3.4.2. Additional Instructions in Dockerfile

You can add additional instructions to the dockerfile using dockerDistTar and Dockerfile task DSL:

Groovy
dockerDistTar {
    instruction 'RUN ls -la'
    environmentVariable 'JAVA_OPTS', '-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap'
}
Kotlin
tasks.named<Dockerfile>("dockerDistTar") {
    instruction("RUN ls -la")
    environmentVariable("JAVA_OPTS", "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap")
}

will result in

FROM openjdk:jre-alpine
LABEL maintainer=user
ADD javaapp-1.0.0-SNAPSHOT.tar /
ENTRYPOINT ["/javaapp-1.0.0-SNAPSHOT/bin/javaapp"]
EXPOSE 8080
RUN ls -la

Or you can use form

Groovy
dockerDistTar.instructionsFromTemplate file('Dockerfile.tmpl')
Kotlin
tasks.named<Dockerfile>("dockerDistTar") {
    instructionsFromTemplate(file("Dockerfile.tmpl"))
}

4. Spring Boot Application Plugin

The plugin com.bmuschko.docker-spring-boot-application is a highly opinionated plugin for projects applying the Spring Boot plugin. Under the covers the plugin preconfigures tasks for creating and pushing Docker images for your Spring Boot application. The default configuration is tweakable via an exposed extension. The plugin reacts to either the java or war plugin.

The plugin only supports projects that use a 2.x version of the Spring Boot plugin.

4.1. Usage

Groovy
plugins {
    id 'java'
    id 'org.springframework.boot' version '2.0.3.RELEASE'
    id 'com.bmuschko.docker-spring-boot-application' version '{project-version}'
}
Kotlin
plugins {
    java
    id("org.springframework.boot") version "2.0.3.RELEASE"
    id("com.bmuschko.docker-spring-boot-application") version "{project-version}"
}

4.2. Extension

The plugin defines an extension with the namespace springBootApplication as a child of the docker namespace. The following properties can be configured:

Property name Type Default value Description

baseImage

Property<String>

openjdk:jre-alpine

The Docker base image used for the Spring Boot application.

ports

ListProperty<Integer>

[8080]

The Docker image exposed ports.

tag

Property<String>

<project.group>/<project.name>:<project.version>

The tag used for the Docker image.

Groovy
docker {
    springBootApplication {
        baseImage = 'openjdk:8-alpine'
        ports = [9090, 8080]
        tag = 'awesome-spring-boot:1.115'
    }
}
Kotlin
docker {
    springBootApplication {
        baseImage.set("openjdk:8-alpine")
        ports.set(listOf(9090, 8080))
        tag.set("awesome-spring-boot:1.115")
    }
}

4.3. Tasks

The plugin provides a set of tasks for your project and preconfigures them with sensible defaults.

Task name Depends On Type Description

dockerSyncArchive

assemble

Sync

Copies the Spring Boot archive to a temporary directory for image creation.

dockerCreateDockerfile

bootJar or bootWar

Dockerfile

Creates the Docker image for the Spring Boot application.

dockerBuildImage

dockerCreateDockerfile

DockerBuildImage

Builds the Docker image for the Spring Boot application.

dockerPushImage

dockerBuildImage

DockerPushImage

Pushes created Docker image to the repository.

4.4. Examples

The following usage examples demonstrate code for common use cases. More scenarios can be found in the functional tests.

4.4.1. Using the Plugin For an Application Run on Tomcat

Groovy
plugins {
    id 'war'
    id 'org.springframework.boot' version '2.0.3.RELEASE'
    id 'io.spring.dependency-management' version '1.0.5.RELEASE'
    id 'com.bmuschko.docker-spring-boot-application'  version '{project-version}'
}

version = '1.0'
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

repositories {
    jcenter()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    providedRuntime 'org.apache.tomcat.embed:tomcat-embed-jasper'
}

docker {
    springBootApplication {
        baseImage = 'openjdk:8-alpine'
    }
}
Kotlin
plugins {
    war
    id("org.springframework.boot") version "2.0.3.RELEASE"
    id("io.spring.dependency-management") version "1.0.5.RELEASE"
    id("com.bmuschko.docker-spring-boot-application") version "{project-version}"
}

version = "1.0"

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

repositories {
    jcenter()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-web")
    providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
    providedRuntime("org.apache.tomcat.embed:tomcat-embed-jasper")
}

docker {
    springBootApplication {
        baseImage.set("openjdk:8-alpine")
    }
}

5. About This Project

5.2. Contributing

Over the years, the plugin has tremendously grown in popularity. Contributions from the community are very welcome. Have a look at the contribution guidelines to get started.

5.3. Development

5.3.1. Executing the Plugin’s Test Suite With Custom Configuration

It is required to install and run Docker Community Edition (CE) on the machine running tests. Please refer to the installation manual for more information. The default setup can be configured with the help of the properties shown in the table below:

Description System/Project Property Environment Variable Default Value

Docker server URL

dockerServerUrl

DOCKER_HOST

unix:///var/run/docker.sock

Docker cert path

dockerCertPath

DOCKER_CERT_PATH

null

Docker private registry URL

dockerPrivateRegistryUrl

DOCKER_REGISTRY_HOST

http://localhost:5000

The following usage examples demonstrates running functional tests against the a Docker instance:

$ ./gradlew functionalTest

OR

$ ./gradlew functionalTest -PdockerServerUrl=unix:///var/run/docker.sock

OR

$ ./gradlew functionalTest -DdockerServerUrl=unix:///var/run/docker.sock

OR

$ export DOCKER_HOST=unix:///var/run/docker.sock && ./gradlew functionalTest

OR

$ ./gradlew functionalTest -PdockerServerUrl=http://192.168.59.103:2376

5.4. Release Process

This section describes the release process designed and implemented for this project. Its main purpose is to explain to developers and maintainers how to prepare and release a new version of the binaries and the documentation.

5.4.1. Tools

The release process uses some external libraries and services described in detail below.

gradle-git

The gradle-git plugin is used to automatically determine the project version. org.ajoberstar.release-opinion is applied in the main build.gradle and configured in ReleasePlugin.kt. Please refer to the plugin documentation for more details.

gradle-git-publish

The gradle-git-publish Gradle plugin is used to publish the documentation to gh-pages branch. It is applied and configured in the DocumentationPlugin.kt file.

Travis CI

Travis CI service is used as our current CI/CD server. Build and deploy jobs are configured in .travis.yml file. Please refer its documentation for more details.

Bintray’s JCenter

Bintray’s JCenter service is used to publish plugin versions. The Bintray plugin uploads artifacts to a remote repository. The plugin configuration can be found in the PublishingPlugin.kt file.

5.4.2. Workflow

The release process is automated to some extent. The following steps describe the workflow.

  1. Developer updates RELEASE_NOTES.md with new planned version.

  2. Developer commits all changes in local working copy.

  3. Developer triggers new version release using the following command: ./gradlew release -Prelease.stage=final -Prelease.scope=[SCOPE] where [SCOPE] can be one of major, minor or patch, and determines which part of the version string <major>.<minor>.<patch> will be incremented.

  4. Gradle executes a build on developer’s machine which calculates new version string, creates new tag with it and pushes to the origin.

  5. When Gradle build is finished, developer’s work is done and the rest of the release process is automated.

  6. After push to the origin, Travis detects new tag and triggers a build.

  7. Travis is instructed to execute release stage when on Git tag.

  8. In this stage Gradle script assembles plugin binaries (with new version) and uploads them to Bintray (credentials are stored as secure variables in Travis). Furthermore, the API docs and the user guide are published to gh-pages branch (the access token is stored as secure variable).

6. Change Log

v4.0.4 (November 4, 2018)

  • Implementation to make DockerBuildImage task incremental and cacheable is not sufficient - Issue 697

v4.0.3 (October 30, 2018)

  • Correctly handle the case where inputDir is not where dockerFile is located - Pull Request 693

v4.0.2 (October 27, 2018)

  • Output file name containing the image ID created by DockerBuildImage should work on Windows - Pull Request 690

v4.0.1 (October 20, 2018)

  • Returned image ID for a DockerBuildImage task should never be null - Pull Request 687

v4.0.0 (October 12, 2018)

  • Breaking Change! Use Provider concept throughout to support lazy evaluation via public API - Pull Request 659

  • Breaking Change! Consumers of this plugin will have to use Java 8 or higher - Pull Request 676

  • Breaking Change! Removal of AbstractReactiveStreamsTask from inherited custom task hierarchy

  • NEW Add tested, multi-lingual user guide - Pull Request 677

  • NEW Make DockerBuildImage task incremental and cacheable - Pull Request 672

  • Introduce method for translating username/password into a PasswordCredentials - Pull Request 668

  • Add @CompileStatic to much of the code base that can support it - Pull Request 676

  • Use appropriate types for Groovy/Kotlin DSL interoperability for reactive streams functionality - Pull Request 678

v3.6.2 (October 2, 2018)

  • DockerCreateContainer gained pid option - Pull Request 652

  • Dockerfile validation takes into account comments - Issue 657

  • Bump docker-java-shaded to rc-5 - Issue 660

  • DockerBuildImage gained network option - Issue 608

  • DockerCreateContainer gained autoRemove option - Issue 639

v3.6.1 (August 21, 2018)

  • Task DockerClient, and the passed dockerClient object, is now cached by configuration - Pull Request 644

  • Task DockerBuildImage gained option cacheFrom - Pull Request 646

v3.6.0 (August 7, 2018)

v3.5.0 (July 24, 2018)

v3.4.4 (July 15, 2018)

  • Task DockerLivenessContainer had its polling logic reworked to be more failure proof.

v3.4.3 (July 8, 2018)

  • Task DockerCreateContainer has its method withEnvVars changed to accept a def, which in turn can be anything (String, Integer, Closure, etc) but will eventually have all its keys/values resolved to java strings. - Pull Request 617

  • Task DockerLivenessContainer had minor verbiage changes to its output. - Pull Request 617

  • Use -all wrapper to better integrate with IDE’s. - Pull Request 617

v3.4.2 (July 7, 2018)

v3.4.1 (July 3, 2018)

  • BUGFIX for task DockerCreateContainer where envs were not being properly honored. - Pull Request 614

v3.4.0 (July 1, 2018)

  • Task Dockerfile now supports multi-stage builds - Pull Request 607

  • When plugin is applied to sub-projects we will additionally search rootProject for repos to use - Pull Request 610

  • Task DockerCreateContainer has deprecated env in favor of envVars which can ONLY be added to with a helper method withEnvVar that can be called N times for setting environment variables. - Pull Request 609

  • Task DockerLivenessProbeContainer has been renamed to DockerLivenessContainer. It’s probe method has been renamed to livnessProbe. Task DockerExecStopContainer had its probe method renamed to execStopProbe. - Pull Request 611

v3.3.6 (June 23, 2018)

  • Task DockerCopyFileToContainer can now copy N number of files via methods withFile and withTarFile. - Pull request 605

v3.3.5 (June 17, 2018)

  • Fix bug within DockerExecContainer when exitCode can be null (default to 0 if so). - Pull request 602

v3.3.4 (June 16, 2018)

  • Task DockerExecContainer gained ability to specify multiple execution commands to be run. - Pull request 600

  • Various tasks had their progress logger output cleaned up. - Pull request 601

v3.3.3 (June 8, 2018)

  • Explicitly call toString() on values in maps passed to Docker API. - Pull request 595

  • Task DockerLivenessProbeContainer gained method lastInspection() which will return the last "docker inspect container" response AFTER execution has completed. - Pull request 596

v3.3.2 (June 5, 2018)

  • Task DockerLivenessProbeContainer now has the probe option set to optional and if NOT defined will fallback to checking if container is in a running state. - Pull request 594

v3.3.1 (June 2, 2018)

  • Various minor refactorings surrounding new task DockerExecStopContainer. - Pull request 592

v3.3.0 (June 1, 2018)

  • Added task DockerClient to pass the raw docker-java client to the onNext closure if defined. - Pull request 589

  • Task DockerCreateContainer will now log the containerName if set, which is the standard within this plugin, otherwise fallback to the just created containerId.

  • Task DockerExecContainer gained option successOnExitCodes to allow user to define a list of successful exit codes the exec is allowed to return and will fail if not in list. Default behavior is to do no check. - Pull request 590

  • Added task DockerLivenessProbeContainer which will poll, for some defined amount of time, a running containers logs looking for a given message and fail if not found. - Pull request 587

  • Added task DockerExecStopContainer to allow the user to execute an arbitrary cmd against a container, polling for it to enter a non-running state, and if that does not succeed in time issue stop request. - Pull request 591

v3.2.9 (May 22, 2018)

  • Fixed a bug in task DockerCreateContainer where option cpuset is now renamed differently in docker-java. - Pull request 585

v3.2.8 (April 30, 2018)

  • Task DockerExecContainer gained option user to specify a user/group. - Pull request 574

  • Task DockerCreateContainer gained option ipV4Address to specify a specific ipv4 address to use. - Pull request 449

  • Bump gradle to 4.7. - Pull request 578

v3.2.7 (April 19, 2018)

  • Task DockerSaveImage gained option useCompression to optionally gzip the created tar. - Pull request 565

  • Add javax.activation dependency for users who are working with jdk9+. - Pull request 572

v3.2.6 (March 31, 2018)

  • Cache docker-java client instead of recreating for every request/task invocation. This is a somewhat big internal change but has a lot of consequences and so it was deserving of its own point release. - Pull request 558

v3.2.5 (March 2, 2018)

  • Added macAddress option to task DockerCreateContainer - Pull request 538

  • Initial work for codenarc analysis - Pull request 537

  • Use of docker-java-shaded library in favor of docker-java proper to get around class-loading/clobbering issues - Pull request 550

  • Honor DOCKER_CERT_PATH env var if present - Pull request 549

  • Task DockerSaveImage will now create file for you should it not exist - Pull request 552

  • Task DockerPushImage will now include tag info in logging if applicable - Pull request 554

  • !!!!! BREAKING: Property inputStream of task DockerLoadImage has been changed from type InputStream to Closure<InputStream>. This was done to allow scripts/code/pipelines to delay getting the image and side-step this property getting configured during gradles config-phase. - Pull request 552

v3.2.4 (February 5, 2018)

v3.2.3 (January 26, 2018)

  • If DockerWaitHealthyContainer is run on an image which was not built with HEALTHCHECK than fallback to using generic status - Pull request 520

v3.2.2 (January 17, 2018)

v3.2.1 (November 22, 2017)

v3.2.0 (September 29, 2017)

  • Update createBind to use docker-java parse method - Pull request 452

  • Allow Docker to cache app libraries dir when DockerJavaApplication plugin is used - Pull request 459

v3.1.0 (August 21, 2017)

  • DockerListImages gained better support for filters - Pull request 414

  • Use alpine:3.4 image in functional tests - Pull request 416

  • DockerBuildImage and DockerCreateContainer gained optional argument shmSize - Pull request 413

  • Added tasks DockerInspectNetwork, DockerCreateNetwork, and DockerRemoveNetwork - Pull request 422

  • Add statically typed methods for configuring plugin with Kotlin - Pull request 426

  • Fix Dockerfile task up-to-date logic - Pull request 433

  • Multiple ENVs are not set the same way as single ENV instructions - Pull request 415

  • DockerCreateContainer changed optional input networkMode to network to better align with docker standatds - Pull request 440

  • The first instruction of a Dockerfile has to be FROM except for Docker versions later than 17.05 - Pull request 435

  • Bump verison of docker-java to 3.0.13 - Commit b2d936

v3.0.10 (July 7, 2017)

v3.0.9 (July 4, 2017)

v3.0.8 (June 16, 2017)

  • Task DockerPullImage gained method getImageId() which returns the fully qualified imageId of the image that was just pulled - Pull request 379

  • Task DockerBuildImage gained property tags which allows for multiple tags to be specified when building an image - Pull request 380

  • Task DockerCreateContainer gained property networkAliases - Pull request 384

v3.0.7 (May 17, 2017)

  • Invoke onNext closures call() method explicitly - Pull request 368

  • Adds new task DockerInspectExecContainer which allows to inspect exec instance - Pull request 362

  • `functionalTest’s can now run against a native docker instance - Pull request 369

  • DockerLogsContainer now preserves leading space - Pull request 370

  • Allow customization of app plugin entrypoint/cmd instructions - Pull request 359

  • Task Dockerfile will no longer be forced as UP-TO-DATE, instead the onus will be put on developers to code this should they want this functionality. - Issue 357

  • Now that functionalTest’s work natively, and in CI, add the test `started, passed and failed logging messages so as to make it absolutely clear to users what is being run vs having no output at all. - Pull request 373

  • Bump docker-java to v`3.0.10` - Pull request 378

v3.0.6 (March 2, 2017)

v3.0.5 (December 27, 2016)

v3.0.4 (December 1, 2016)

v3.0.3 (September 6, 2016)

v3.0.2 (August 14, 2016)

v3.0.1 (July 6, 2016)

  • Simplify Gradle TestKit usage - Pull request 225

  • Ensure tlsVerify is set in addition to certPath for DockerClientConfig setup - Pull request 230

  • Upgrade to Gradle 2.14.

v3.0.0 (June 5, 2016)

  • Task DockerLogsContainer gained attribute sink - Pull request 203

  • Task DockerBuildImage will no longer insert extra newline as part of build output - Pull request 206

  • Upgrade to docker-java 3.0.0 - Pull request 217

  • Fallback to buildscript.repositories for internal dependency resolution if no repositories were defined - Pull request 218

  • Added task DockerExecContainer - Pull request 221

  • Added task DockerCopyFileToContainer - Pull request 222

  • Task DockerCreateContainer gained attribute restartPolicy - Pull request 224

  • Remove use of Gradle internal methods.

  • Added ISSUES.md file.

  • Upgrade to Gradle 2.13.

v2.6.8 (April 10, 2016)

v2.6.7 (March 10, 2016)

  • Upgrade to Gradle 2.11.

  • Bug fix when copying single file from container and hostPath is set to directory for DockerCopyFileFromContainer - Pull request 163

  • Step reports are now printed to stdout by default for DockerBuildImage - Pull request 145

  • UP-TO-DATE functionality has been removed from DockerBuildImage as there were too many corner cases to account for - Pull request 172

v2.6.6 (February 27, 2016)

v2.6.5 (January 16, 2016)

v2.6.4 (December 24, 2015)

v2.6.3 (December 23, 2015)

  • Expose force and removeVolumes properties on DockerRemoveContainer - Pull request 129.

v2.6.2 (December 22, 2015)

  • Expose support for LogDriver on DockerCreateContainer - Pull request 118.

  • Upgrade to Docker Java 2.1.2.

v2.6.1 (September 21, 2015)

  • Correct the withVolumesFrom call on DockerCreateContainer task which needs to get a VolumesFrom[] array as the parameter - Pull request 102.

  • Upgrade to Docker Java 2.1.1 - Pull request 109.

v2.6 (August 30, 2015)

  • Upgrade to Docker Java 2.1.0 - Pull request 92. Note: The Docker Java API changed vastly with v2.0.0. The tasks DockerBuildImage, DockerPullImage and DockerPushImage do not provide a response handler anymore. This is a breaking change. Future versions of the plugin might open up the response handling again in some way.

  • DockerListImages with filter call a wrong function from ListImagesCmdImpl.java - Issue 105.

v2.5.2 (August 15, 2015)

  • Fix listImages task throwing GroovyCastException - Issue 96.

  • Add support for publishAll in DockerCreateContainer - Pull request 94.

  • Add optional dockerFile option to the DockerBuildImage task - Pull request 47.

v2.5.1 (July 29, 2015)

  • Adds Dockerfile support for the LABEL instruction - Pull request 86.

  • Usage of docker-java library v1.4.0. Underlying API does not provide setting port bindings for task DockerStartContainer anymore. Needs to be set on DockerCreateContainer.

v2.5 (July 18, 2015)

  • Expose response handler for DockerListImages task - v[Issue 75].

  • Pass in credentials when building an image - Issue 76.

v2.4.1 (July 4, 2015)

v2.4 (May 16, 2015)

  • Added missing support for properties portBindings and cpuset in CreateContainer - Pull request 66.

  • Expose response handlers so users can inject custom handling logic - Issue 65.

  • Upgrade to Gradle 2.4 including all compatible plugins and libraries.

v2.3.1 (April 25, 2015)

v2.3 (April 18, 2015)

v2.2 (April 12, 2015)

v2.1 (March 24, 2015)

  • Renamed property registry to registryCredentials for plugin extension and tasks implementing RegistryCredentialsAware to better indicate its purpose. Note: This is a breaking change.

v2.0.3 (March 20, 2015)

  • Allow for specifying port bindings for container start command. - Issue 30.

  • Throw an exception if an error response is encountered - Issue 37.

  • Upgrade to Gradle 2.3.

v2.0.2 (February 19, 2015)

  • Set source and target compatibility to Java 6 - Issue 32.

v2.0.1 (February 10, 2015)

  • Extension configuration method for DockerJavaApplicationPlugin needs to be registered via extension instance - Issue 28.

v2.0 (February 4, 2015)

  • Upgrade to Gradle 2.2.1 including all compatible plugins and libraries.

v0.8.3 (February 4, 2015)

  • Add project group to default tag built by Docker Java application plugin - Issue 25.

v0.8.2 (January 30, 2015)

  • Expose method for task Dockerfile for providing vanilla Docker instructions.

v0.8.1 (January 24, 2015)

v0.8 (January 7, 2014)

  • Allow for pushing to Docker Hub - Issue 18.

  • Better handling of API responses.

  • Note: Change to plugin extension. The property docker.serverUrl is now called docker.url. Instead of docker.credentials, you will need to use docker.registry.

v0.7.2 (December 23, 2014)

  • Dockerfile task is always marked UP-TO-DATE after first execution - Issue 13.

  • Improvements to Dockerfile task - Pull request 16.

  • Fixed wrong assignment of key field in environment variable instruction.

  • Allow for providing multiple ports to the expose instruction.

v0.7.1 (December 16, 2014)

  • Fixed entry point definition of Dockerfile set by Java application plugin.

v0.7 (December 14, 2014)

  • Allow for properly add user-based instructions to Dockfile task with predefined instructions without messing up the order. - Issue 12.

  • Renamed task dockerCopyDistTar to dockerCopyDistResources to better express intent.

v0.6.1 (December 11, 2014)

  • Allow for setting path to certificates for communicating with Docker over SSL - Issue 10.

v0.6 (December 7, 2014)

  • Usage of docker-java library v0.10.4.

  • Added Docker Java application plugin.

  • Better documentation.

v0.5 (December 6, 2014)

  • Fixed implementations of tasks DockerPushImage and DockerCommitImage - Issue 11.

v0.4 (November 27, 2014)

  • Added task for creating a Dockerfile.

v0.3 (November 23, 2014)

  • Usage of docker-java library v0.10.3.

  • Changed package name to com.bmuschko.gradle.docker.

  • Changed group ID to com.bmuschko.

  • Adapted plugin IDs to be compatible with Gradle’s plugin portal.

v0.2 (June 19, 2014)

  • Usage of docker-java library v0.8.2.

  • Provide custom task type for push operation.

  • Support for using remote URLs when building image - Issue 3.

v0.1 (May 11, 2014)

  • Initial release.