Building Java Containers With Jib
Introduction
Containerization has become a crucial part of modern software development, especially with the rise of microservices and cloud-native architectures. For Java developers, containerizing applications traditionally involves writing Dockerfiles, managing Docker daemon dependencies, and dealing with image layer optimizations. Enter Jib: an open-source tool from Google that simplifies the containerization of Java applications, eliminating the need for Dockerfiles and enabling seamless integration into your existing build pipeline.
In this blog post, we'll explore what Jib is, how it works, and how you can use it to containerize your Java applications effortlessly.
What is Jib?
Jib is an open-source Java library that allows you to build optimized Docker and OCI (Open Container Initiative) images for your Java applications without the need for a Dockerfile or Docker daemon. It integrates directly with your Java build process and handles all the complexities of containerization, such as layer caching, image optimization, and registry communication.
Jib comes in two flavors:
Jib Maven Plugin: Integrates with Maven-based projects.
Jib Gradle Plugin: Integrates with Gradle-based projects.
Jib Core: A Java library that gives you programmatic control over containerization, allowing advanced customization.
Why Use Jib?
Here are a few reasons why Jib stands out:
No Dockerfile Required: Jib automatically handles the containerization process, so you don't need to write or maintain Dockerfiles.
No Docker Daemon Required: Jib can build images without needing Docker installed on your machine.
Fast Builds: Jib optimizes the image layers, ensuring that only changed files are re-pushed, significantly speeding up the build process.
Build-Time Integration: Jib integrates with your Maven or Gradle build process, making it easy to incorporate containerization into your CI/CD pipeline.
Rich Customization: With Jib Core, you can programmatically define your image creation process, allowing for advanced customization beyond what is possible with traditional Dockerfiles.
What does Jib do?
Jib handles all steps of packaging your application into a container image. You don't need to know best practices for creating Dockerfiles or have Docker installed.
Docker build flow:
Jib build flow:
Jib organizes your application into distinct layers; dependencies, resources, and classes; and utilizes Docker image layer caching to keep builds fast by only rebuilding changes. Jib's layer organization and small base image keeps overall image size small which improves performance and portability.
Getting Started with Jib Maven Plugin
Let's dive into a practical example of using Jib to containerize a Spring Boot application.
1.Add the Jib Plugin to Your Maven Project
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.3.2</version>
<configuration>
<to>
<image>registry.hub.docker.com/${env.DOCKER_USERNAME}/hello-world-jib</image>
<tags>
<tag>maven-plugin</tag>
</tags>
<auth>
<username>${env.DOCKER_USERNAME}</username>
<password>${env.DOCKER_PASSWORD}</password>
</auth>
</to>
</configuration>
</plugin>
2.Build And Push The Image To A Container Registry
mvn compile jib:build
Getting Started with Jib Core
1.Add Jib Core Dependency
<dependency>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-core</artifactId>
<version>0.24.0</version>
</dependency>
2.Build the Application
mvn clean package
3.Write a Jib Configuration Class
import com.google.cloud.tools.jib.api.Containerizer;
import com.google.cloud.tools.jib.api.ImageReference;
import com.google.cloud.tools.jib.api.Jib;
import com.google.cloud.tools.jib.api.RegistryImage;
import com.google.cloud.tools.jib.api.buildplan.AbsoluteUnixPath;
import com.google.cloud.tools.jib.api.buildplan.FileEntriesLayer;
import com.google.cloud.tools.jib.api.buildplan.Port;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class JibDockerizer {
public static void main(String[] args) throws Exception{
// Retrieve credentials from environment variables
String dockerUsername = System.getenv("DOCKER_USERNAME");
String dockerPassword = System.getenv("DOCKER_PASSWORD");
Path jarFile = Paths.get("target/jib-demo-0.0.1-SNAPSHOT.jar");
if (Files.exists(jarFile)) {
// Define the base image
ImageReference baseImage = ImageReference.parse("openjdk:17-jdk-alpine");
// Define the target Docker image name (Docker Hub repository)
String dockerHubRepository = dockerUsername + "/hello-world-jib";
String imageTag = "jib-core";
ImageReference targetImage = ImageReference.of("docker.io", dockerHubRepository, imageTag);
// Create the layer with your JAR file
FileEntriesLayer jarLayer = FileEntriesLayer.builder()
.addEntry(jarFile, AbsoluteUnixPath.get("/app/my-springboot-app.jar"))
.build();
// Use Jib to containerize the application
Jib.from(baseImage)
.addFileEntriesLayer(jarLayer)
.setEntrypoint("java", "-jar", "/app/my-springboot-app.jar")
.setExposedPorts(Port.tcp(8080))
.containerize(Containerizer.to(RegistryImage.named(targetImage)
.addCredential(dockerUsername, dockerPassword)));
}
System.out.println("Docker image built and pushed successfully!");
}
}
4.Run the JibDockerizer
java JibDockerizer
The images got built and pushed to Dockerhub successfully!๐
Conclusion
Jib simplifies containerizing Java applications by eliminating the need for Dockerfiles and a local Docker daemon. It integrates seamlessly with Maven, Gradle, and Jib Core, offering optimized, reproducible Docker images that fit perfectly into modern CI/CD workflows. By using Jib, you can streamline your build process, enhance deployment efficiency, and ensure consistency in your cloud-native applications. Embrace Jib to take your containerization efforts to the next level.
Happy containerizing!
Github Link: https://github.com/Haaris-Sayyed/java-containers-with-jib
Subscribe to my newsletter
Read articles from Haaris Sayyed directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by