/gradle-docker-plugin

Gradle plugin for managing Docker images and containers.

Primary LanguageGroovyApache License 2.0Apache-2.0

Build Status Download Stackoverflow Gitter

Gradle Docker plugin

Docker Logo

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 >= 2.5 to work properly.

Usage

To use the plugin, include in your build script:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.bmuschko:gradle-docker-plugin:X.Y.Z'
    }
}

Provided plugins

The JAR file comes with two 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.

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. To use the plugin, include the following code snippet in your build script:

apply plugin: 'com.bmuschko.docker-remote-api'

If you would like to use this plugin from a build file which is not the main build file you must apply/use it like this:

build.gradle
apply from: 'gradle/docker.gradle'
gradle/docker.gradle
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.bmuschko:gradle-docker-plugin:X.Y.Z'
    }
}

// use fully qualified class name
apply plugin: com.bmuschko.gradle.docker.DockerRemoteApiPlugin

// import task classes
import com.bmuschko.gradle.docker.tasks.image.*

// use task classes

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.

repositories {
    mavenCentral()
}

Custom task types

Misc

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

Type Description

DockerInfo

Displays system-wide information.

DockerVersion

Show the docker version information.

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.

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.

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.

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.

Extras

The plugin provides the following additional tasks:

Type Description

DockerWaitHealthyContainer

Blocks until the container for a given id becomes healthy.

Extension properties

The plugin defines the following extension properties in the docker closure:

Property name Type Default value Description

url

String

see below

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

certPath

File

null

The path to certificates for communicating with Docker over SSL.

apiVersion

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 OperatingSystem and Environment:

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

String

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

The registry URL.

username

String

null

The registry username.

password

String

null

The registry password.

email

String

null

The registry email address.

Extension examples

Working with a TLS-enabled Docker instance

Starting with Docker version 1.3, TLS is enabled by default. Please consult the Docker documentation "Running Docker with https" 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.

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'
    }
}
Working with Google Cloud and using a key file
docker {
    registryCredentials {
        url = 'https://gcr.io'
        username = '_json_key'
        password = file('keyfile.json").text
    }
}
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.

docker {
    url = '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.

Usage examples

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

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.

apply plugin: 'com.bmuschko.docker-remote-api'

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'
    maintainer 'Benjamin Muschko "benjamin.muschko@gmail.com"'
}

task buildImage(type: DockerBuildImage) {
    dependsOn createDockerfile
    inputDir = createDockerfile.destFile.parentFile
    tag = 'bmuschko/myimage:latest'
}

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

onError

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.

apply plugin: 'com.bmuschko.docker-remote-api'

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

task removeContainer(type: DockerRemoveContainer) {
    targetContainerId { "container-that-does-not-exist" }
    onError { exception ->
        if (!exception.message.contains('No such container')) // ignore exception if container does not exist otherwise throw it
            throw exception
    }
}

onNext

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 onException 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.

apply plugin: 'com.bmuschko.docker-remote-api'

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

task logContainer(type: DockerLogsContainer) {
    targetContainerId { "container-that-does-exist" }
    follow = true
    tailAll = true
    onNext { message ->
        logger.quiet message.toString() // each log message from the container will be passed as it's made available
    }
}

onComplete

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.

apply plugin: 'com.bmuschko.docker-remote-api'

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

task removeContainer(type: DockerRemoveContainer) {
    targetContainerId { "container-that-does-exist" }
    onComplete {
        println "Executes first"
    }
    doLast {
        println "Executes second"
    }
}

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.

apply plugin: 'com.bmuschko.docker-remote-api'

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']
}

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

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

task functionalTestMyApp(type: Test) {
    dependsOn startMyAppContainer
    finalizedBy stopMyAppContainer
}

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:

apply plugin: 'com.bmuschko.docker-remote-api'

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_${buildMyAppImage.buildTagName}"
}

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

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

    // 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
}

Java application plugin

The plugin com.bmuschko.docker-java-application is a highly opinonated 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. To use the plugin, include the following code snippet in your build script:

apply plugin: 'com.bmuschko.docker-java-application'

Extension properties

The plugin defines the following extension properties in the javaApplication closure:

Property name Type Default value Description

baseImage

String

java

The Docker base image used for Java application.

exec

Closure

Create ENTRYPOINT using script from Application plugin

The ENTRYPOINT and/or CMD Dockerfile instructions

maintainer

String

Value of user.home system property

The name and email address of the image maintainer.

port

Integer

8080

The Docker image entry point port used for the Java application (Deprecated)

ports

Integer[]

[]

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

tag

String

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

The tag used for the Docker image.

Usage example

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

exec property

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

Usage example

docker {
    javaApplication {
        baseImage = 'dockerfile/java:openjdk-7-jre'
        maintainer = 'Benjamin Muschko "benjamin.muschko@gmail.com"'
        ports = [9090, 5701]
        tag = 'jettyapp:1.115'
        exec {
            defaultCommand 'server'
            entryPoint 'myApp/bin/containerLaunch.sh'
        }
    }
}

Default 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.

Usage examples

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

apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'com.bmuschko.docker-java-application'

version = '1.0'
sourceCompatibility = 1.7

repositories {
    mavenCentral()
}

dependencies {
    compile '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"'
    }
}

Additional instructions in Dockerfile

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

dockerDistTar {
    instruction {'RUN ls -la'}
    environmentVariable('JAVA_OPTS', '-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap')
}

docker {
    javaApplication {
    }
}

will result in

FROM java
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

project.tasks.getByName("dockerDistTar").instructionsFromTemplate file("Dockerfile.tmpl")

FAQ

Executing the plugin’s test suite with custom configuration

The default setup can be configured with the help of the properties shown in the table below:

Description System/Project/Environment variable Default Value

Docker server URL

dockerServerUrl/dockerServerUrl/DOCKER_HOST

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

Docker cert path

dockerCertPath/dockerCertPath/DOCKER_CERT_PATH

null

Docker private registry URL

dockerPrivateRegistryUrl/dockerPrivateRegistryUrl/DOCKER_REGISTRY_HOST

http://localhost:5000

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

./gradlew build functionalTest

OR

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

OR

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

OR

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

OR

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

Using a Vagrant box to bootstrap Docker

Docker does not need to be installed on the local or another remote machine. This project provides a Vagrant image with the proper setup to bootstrap a Docker installation. The Vagrantfile can be found under the directory vagrant. To use the Vagrant box simply start it manually.

vagrant up

Automatically starts and stop Vagrant box for executing functional tests

An installation of VirtualBox and Vagrant is required. See the "Getting Started" guide for more information.

Alternatively, you can configure the project to bootstrap the Vagrant box as needed. Use the command line option -PbootstrapDocker=true for this purpose.

./gradlew functionalTest -PbootstrapDocker=true