Introduction
When I joined PayPay, one of the first things I tried to understand was how our services were containerized.
A common exercise when joining a new backend team is to look at the Dockerfiles used across services as they often reveal interesting patterns:
Which base images are used
Whether the builds are optimized
If multi-stage builds are implemented
Opportunities for reducing image size or improving caching
So naturally, I went looking for the Dockerfile.
But to my surprise… I couldn't find one.
After digging a bit deeper, I realized something interesting. The project wasn’t using a Dockerfile at all. Instead, it was using Jib.
📦 Enter Jib
Imagine shipping a Java microservice where changing a single line of code doesn’t force your CI pipeline to rebuild a massive container image.
That’s exactly what Jib enables.
Jib is an open-source container image builder for Java applications that:
Eliminates the need for a Dockerfile
Does not require a Docker daemon
Integrates directly with Maven and Gradle
Instead of packaging your application as a single fat layer, Jib understands Java project structure and splits your application into optimized layers:
Runtime (base image)
Dependencies
Resources
Application classes
Because of this layered structure, when you change only your application code, only the top layer is rebuilt and pushed.
The result?
In this post, we'll explore how Jib works, when to use it, and how it compares to traditional Dockerfiles.
🚀 What's Jib?
If you build Java applications and ship containers, you’ve probably written Dockerfiles like this:
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY target/app.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
It works.
But it’s not optimized for Java.
This is where Jib changes the game.
🧱 The Problem With Traditional Docker Builds
Before Jib, containerizing Java apps required:
Writing and maintaining Dockerfiles
Installing Docker everywhere (including CI)
Packaging fat JARs
Rebuilding full images for small code changes
Manually optimizing layers
Even a small code change could invalidate caching and rebuild everything.
That’s inefficient.
🧠 How Jib Works
Jib builds container images by splitting your app into logical layers:
Base Image (JRE)
Dependencies
Resources
Application classes
This means:
This drastically improves CI speed.
🛠️ Getting Started with Jib
Maven Setup
Add this to your pom.xml:
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>3.4.0</version>
<configuration>
<to>
<image>ghcr.io/yourorg/yourapp</image>
</to>
</configuration>
</plugin>
Build & push:
mvn compile jib:build
Gradle Setup
plugins {
id("com.google.cloud.tools.jib") version "3.4.0"
}
jib {
to {
image = "ghcr.io/yourorg/yourapp"
}
}
Build:
./gradlew jib
⚔️ Dockerfile vs Jib - Which Is Better?
This is the real question.
The answer depends on some of the use cases.
✅ When Jib Is Better
1. Standard Java Microservices
Spring Boot
Micronaut
Quarkus
Plain Maven/Gradle apps
Jib integrates directly with your build system.
2. Faster CI/CD Pipelines
Jib:
Does not require a Docker daemon
Builds incremental layers
Pushes smaller diffs
Produces reproducible builds
If CI time matters, Jib usually wins.
3. Developer Simplicity
No Dockerfile. No manual layering. Less DevOps friction.
🏗️ When Dockerfile Is Better
1. OS-Level Customization
If you need:
apt-get install
Native libraries
Custom shell scripts
Jib does not support arbitrary RUN commands.
Dockerfile wins here.
2. Polyglot Applications
If your container includes:
Node + Java
Python + Java
Multiple build tools
Custom entrypoints
Dockerfile provides full flexibility.
3. Complex Multi-Stage Builds
Example:
Dockerfile is more powerful here.
📊 Side-by-Side Comparison
| Feature |
Jib |
Dockerfile |
| Requires Docker daemon |
❌ No |
✅ Yes |
| Requires Dockerfile |
❌ No |
✅ Yes |
| OS Customization |
❌ Limited |
✅ Full |
| Java Layer Optimization |
✅ Automatic |
❌ Manual |
| CI/CD Simplicity |
✅ High |
⚠️ Medium |
| Multi-language builds |
❌ No |
✅ Yes |
| Learning Curve |
Low |
Medium |
🎯 Real-World Scenarios
Scenario A: 20 Spring Boot Microservices
Kubernetes
GitHub Actions
CI cost matters
👉 Jib is usually the better choice.
Scenario B: Enterprise App With Native Dependencies
Custom Alpine base image
OS packages
Hardening scripts
Multi-stage builds
👉 Dockerfile is better.
Scenario C: Small Startup Team
Java-only stack
No DevOps team
Want fast pipelines
👉 Jib simplifies everything.
Because Jib separates dependencies and classes:
Code-only changes rebuild in seconds
Docker layer cache invalidation is minimized
CI builds are more predictable
In large microservice ecosystems, this adds up significantly.
🚀 Closing Thoughts
Jib is optimized for:
Java developer productivity.
Dockerfile is optimized for:
Infrastructure control.
If you build modern Java microservices → Start with Jib.
If you need deep OS-level control → Use Dockerfile.
Containerization doesn’t have to be complicated. If your stack is Java-centric and you value speed, reproducibility, and developer autonomy, then Jib is one of the smart tools you can adopt today.