Build docker images with gradle
In this article, we will understand how to create docker images from gradle build for a java application with example.
Before moving further, make sure that you have following installed on your system
- Gradle
- Docker
For this article, we will use a simple java application having a single file with main class as shown below
public class Main { public static void main(String[] args) { System.out.println("Hello, World!"); } }
Gradle does not offer an inbuilt functionality to create a docker image.
For this, we need to use a plugin and the plugin to build a docker image with gradle, use the Jib plugin. This plugin provides a simple way to build and publish container images using gradle.
Following are the steps for configuring your gradle application to create docker image
1. Add jib gradle plugin.
plugins { id 'com.google.cloud.tools.jib' version '3.3.1' }
2. Add jib task to create an image from your application and push it to the registry as shown below
jib { from { image = 'openjdk:11-jdk-slim' } to { image = 'demo-app' } }
In this example, we’re using the openjdk:11-jdk-slim base image and tagging our image as demo-app.
When you execute this task with gradle with command
gradle jib
When the above command is executed, below is the workflow that is executed step by step
1. Gradle compiles the java code and generates the class files.
2. Jib
creates a docker image with the details specified in jib task such as which base image to use and the name of the image.
3. Jib
copies the compiled class files into the docker image, along with any dependencies specified in your gradle build.
4. Jib
configures the entry point for the docker image to be the java
command, along with the appropriate classpath and command line arguments to run the application.
5. Jib
then builds the docker image and publishes it to the registry.
In this case, since there is a single java file, jib
sets it to be the main class.
If there are multiple files, then you can specify the main class with container
property under jib
task as shown below.
jib { from { image = 'openjdk:11-jdk-slim' } to { image = 'demo-app' } container { mainClass = 'com.codippa.Main' jvmFlags = ['-Xms512m', '-Xmx1024m'] } }
You can also create a jar from the application file by supplying the jar
task and providing it the Main-Class
attribute.
Below is a complete gradle file, which specifies the plugins, dependencies and also contains jar
and jib
tasks.
plugins { id 'java' id 'com.google.cloud.tools.jib' version '3.3.1' } group 'com.codippa' version '1.0-SNAPSHOT' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot: spring-boot-starter-web:2.7.5' } jar { manifest { attributes 'Main-Class': 'com.codippa.Main' } } jib { from { image = 'openjdk:11-jdk-slim' } to { image = 'demo-app' } container { mainClass = 'com.codippa.Main' jvmFlags = ['-Xms512m', '-Xmx1024m'] } }
Default tag of the image will be latest. If you want another tag for the image, then specify it after the image name as below
jib { from { image = 'openjdk:11-jdk-slim' } to { image = 'demo-app:1.0-SNAPSHOT' } }
or with tags option
jib { from { image = 'openjdk:11-jdk-slim' } to { image = 'demo-app' tags = ['1.0-SNAPSHOT'] } }
If you do not specify any registry, then by default it will publish to docker hub. If you want to push the image to another registry with, then specify the registry URL along with the image name as shown below
plugins { id 'com.google.cloud.tools.jib' version '3.3.1' } jib { to { image = 'docker.io/<repository>/demo-app:1.0-SNAPSHOT' auth { username = "<username>" password = "<password>" } } }
The auth
block provides the username and password for authenticating with the container registry.
Till now, we looked at a simple image that is built on jdk image and contains the application.
It might happen that your application image has additional instructions such as copying files, downloading libraries, exposing ports etc.
You can use an external Dockerfile to build application images with
buildDocker
configuration option inside jib task.buildDocker provides a lot of customization options for image creation process such as the name and tag of the image, the Dockerfile location, and the options to use for the
docker build
command. Below are the options that can be configured with buildDocker
configuration
1. dockerBuildDirectory
: The directory containing the Dockerfile to use for the build.
This can be an absolute path or a relative path from the project root directory.
2. dockerBuildContext
: The context directory to use for the docker build.
This can be an absolute path or a relative path from the project root directory.
3. dockerfile
: The name of the dockerfile to use for the build.
This can be an absolute path or a relative path from the dockerBuildDirectory
.
4. labels
: Additional labels to add to the docker image.
5. env
: Additional environment variables to set during the docker build.
6. volumes
: Additional volumes to mount during the docker build.
7. entrypoint
: The entry point to use for the docker image.
8. user
: The user to use for the docker image.
9. ports
: The ports to expose on the docker image.
10. buildArgs
: Additional build arguments to pass to the docker build.
An example of these options is given ahead
jib { from { image = 'openjdk:11-jre-slim' } to { image = 'demo-registry/demo-image:1.0-SNAPSHOT' } container { mainClass = 'com.codippa.Main' } buildDocker { dockerBuildDirectory = 'app' dockerfile = 'app-dockerfile' labels = ['version': '1.0'] ports = ['8080', '8443'] } }
Creating local images
jib
task is used to create and push images to docker registry.
If you want to create an image and run it locally with docker, then jib plugin provides another task jibDockerBuild
for this.
Simply execute
gradle jibDockerBuild
and it will create a docker image with default configuration and publish it to local docker daemon.
jibDockerBuild
task can be customized as per requirement, such as specifying a custom base image or Dockerfile, by adding configuration options to your build.gradle
file.
Example,
plugins { id 'com.google.cloud.tools.jib' version '3.3.1' } jib { from { image = 'openjdk:11-jre-slim' } to { image = 'app-registry/demo-app:1.0-SNAPSHOT' } container { mainClass = 'com.codippa.Main' } } jibDockerBuild { dockerBuildDirectory = 'app' dockerfile = 'appdockerfile' labels = ['version': '1.0'] ports = ['8080', '8443'] }
Once the jibDockerBuild
task succeeds, you can run the image locally with docker run command as below
docker run demo-app:1.0-SNAPSHOT
Remember that jibDockerBuild
task requires docker installed locally on your system.
If you try to run the jibDockerBuild
task without a local Docker daemon, you’ll see an error message as shown below
> Task :jib FAILED
No installed Docker daemon detected. Please install Docker and try again.
So make sure you have docker installed and running before using the jibDockerBuild
task.