1. Overview
In this tutorial, we’ll take a look at Jib and how it simplifies containerization of Java applications.
We’ll take a simple Spring Boot application and build its Docker image using Jib. And then we’ll also publish the image to a remote registry.
And make sure also to refer to our tutorial about dockerizing Spring Boot applications using dockerfile and docker tool.
2. Introduction to Jib
Jib is an open-source Java tool maintained by Google for building Docker images of Java applications. It simplifies containerization since with it, we don’t need to write a dockerfile.
And actually, we don’t even have to have docker installed to create and publish the docker images ourselves.
Google publishes Jib as both a Maven and a Gradle plugin. This is nice because it means that Jib will catch any changes we make to our application each time we build. This saves us separate docker build/push commands and simplifies adding this to a CI pipeline.
There are a couple of other tools out there, too, like Spotify’s docker-maven-plugin and dockerfile-maven plugins, though the former is now deprecated and the latter requires a dockerfile.
3. A Simple Greeting App
Let’s take a simple spring-boot application and dockerize it using Jib. It’ll expose a simple GET endpoint:
http://localhost:8080/greeting
Which we can do quite simply with a Spring MVC controller:
@RestController public class GreetingController { private static final String template = "Hello Docker, %s!"; private final AtomicLong counter = new AtomicLong(); @GetMapping("/greeting") public Greeting greeting(@RequestParam(value="name", defaultValue="World") String name) { return new Greeting(counter.incrementAndGet(), String.format(template, name)); } }
4. Preparing the Deployment
We’ll also need to set ourselves up locally to authenticate with the Docker repository we want to deploy to.
For this example, we’ll provide our DockerHub credentials to .m2/settings.xml:
<servers> <server> <id>registry.hub.docker.com</id> <username><DockerHub Username></username> <password><DockerHub Password></password> </server> </servers>
There are other ways to provide the credentials, too. The recommended way by Google is to use helper tools, which can store the credentials in an encrypted format in the file system. In this example, we could have used docker-credential-helpers instead of storing plain-text credentials in settings.xml, which is much safer, though simply out of scope for this tutorial.
5. Deploying to Docker Hub with Jib
Now, we can use jib-maven-plugin, or the Gradle equivalent, to containerize our application with a simple command:
mvn compile com.google.cloud.tools:jib-maven-plugin:0.9.10:build -Dimage=$IMAGE_PATH
where IMAGE_PATH is the target path in the container registry.
For example, to upload the image baeldungjib/spring-jib-app to DockerHub, we would do:
export IMAGE_PATH=registry.hub.docker.com/baeldungjib/spring-jib-app
And that’s it! This will build the docker image of our application and push it to the DockerHub.
We can, of course, upload the image to Google Container Registry or Amazon Elastic Container Registry in a similar way.
6. Simplifying the Maven Command
Also, we can shorten our initial command by configuring the plugin in our pom instead, like any other maven plugin.
<project> ... <build> <plugins> ... <plugin> <groupId>com.google.cloud.tools</groupId> <artifactId>jib-maven-plugin</artifactId> <version>0.9.10</version> <configuration> <to> <image>${image.path}</image> </to> </configuration> </plugin> ... </plugins> </build> ... </project>
With this change, we can simplify our maven command:
mvn compile jib:build
7. Customizing Docker Aspects
By default, Jib makes a number of reasonable guesses about what we want, like the FROM and the ENTRYPOINT.
Let’s make a couple of changes to our application that are more specific to our needs.
First, Spring Boot exposes port 8080 by default.
But, let’s say, we want to make our application run on port 8082 and make it exposable through a container.
Of course, we’ll make the appropriate changes in Boot. And, after that, we can use Jib to make it exposable in the image:
<configuration> ... <container> <ports> <port>8082</port> </ports> </container> </configuration>
Or, let’s say we need a different FROM. By default, Jib uses the distro-less java image.
If we want to run our application on a different base image, like alpine-java, we can configure it in a similar way:
<configuration> ... <from> <image>openjdk:alpine</image> </from> ... </configuration>
We configure tags, volumes, and several other Docker directives in the same way.
8. Customizing Java Aspects
And, by association, Jib supports numerous Java runtime configurations, too:
- jvmFlags is for indicating what startup flags to pass to the JVM.
- mainClass is for indicating the main class, which Jib will attempt to infer automatically by default.
- args is where we’d specify the program arguments passed to the main method.
Of course, make sure to check out Jib’s documentation to see all the configuration properties available.
9. Conclusion
In this tutorial, we saw how to build and publish docker images using Google’s Jib, including how to access the docker directives and Java runtime configurations through Maven.
As always, the source code for this example is available over on Github.