Dockerizing Java Apps using Jib

**

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
.

**

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

**

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));
    }
}

**

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.

**

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

**

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
.

**

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.

Leave a Reply

Your email address will not be published.