This is a cache of https://developer.ibm.com/tutorials/quarkus-basics-06/. It is a snapshot of the page as it appeared on 2026-03-24T01:25:29.516+0000.
Containerizing Quarkus applications and deploying them with Kubernetes
IBM Developer

Tutorial

Containerizing Quarkus applications and deploying them with Kubernetes

Simplifying cloud-native applications

In this tutorial, you will package a simple Quarkus application into a container image and deploy it to Kubernetes. You don’t need to write Kubernetes YAML by hand, Quarkus can generate the manifests for you during the build. By using Quarkus to help package your app, the developer experience is smooth and consistent with the Quarkus philosophy of convention over configuration.

Containers and Quarkus

In the cloud, applications run in containers. Containers package everything an app needs, code, runtime, and libraries, into one portable unit. Quarkus applications are small and fast, which makes them ideal for containerized environments like Kubernetes and OpenShift.

Quarkus supports multiple container build strategies, so you can choose the one that works best for your team:

  • Jib: A Maven or Gradle plugin that builds container images without a Dockerfile. Great for CI/CD pipelines.
  • Dockerfile or Podmanfile: The traditional way where you write a file and build with docker build or podman build. -Quarkus container-image extension: Lets you build images directly with ./mvnw package -Dquarkus.container-image.build=true.
  • Buildpacks: Uses Cloud Native Buildpacks to create images without Dockerfiles.

for this tutorial, we’ll use Jib. The extension quarkus-container-image-jib is powered by Jib for performing container image builds. The major benefit of using Jib with Quarkus is that all the dependencies (everything found under target/lib) are cached in a different layer than the actual application making rebuilds really fast and small (when it comes to pushing). Another important benefit of using this extension is that it can create a container image without having to have any dedicated client side tooling (like Docker) or running daemon processes (like the Docker daemon) when all that is needed is the ability to push to a container image registry.

Step 1. Set up a new Quarkus project

Before you begin, make sure that you have this software:

  • JDK 17+ (Quarkus 3 requires at least Java 17)
  • Apache Maven 3.8.1+
  • A container runtime such as Podman or Docker
  • An IDE like IntelliJ, VS Code, or Eclipse

Generate a new Quarkus project with the Jib extension:

mvn io.quarkus.platform:quarkus-maven-plugin:create \
    -DprojectGroupId=com.ibm.developer \
    -DprojectArtifactId=jib-tutorial \
    -DclassName="com.ibm.developer.GreetingResource" \
    -Dpath="/hello" \
    -Dextensions="rest-jackson,quarkus-container-image-jib,kubernetes"
cd jib-tutorial

Quarkus is built around extensions. Instead of writing custom Dockerfiles or YAML, you can add extensions that handle container images and Kubernetes integration for you. This is part of Quarkus’s philosophy: let the framework do the heavy lifting so you can focus on your code.

for this step, we need two new extensions:

  • container-image-jib. This extension builds container images by using Jib, a Java tool that creates images directly from your project. You don’t need Docker or Podman installed for this. Jib takes your compiled application and builds a layered container image. This makes rebuilding faster and keeps your images small.
  • kubernetes. This extension generates Kubernetes manifests for you. When you build your project, Quarkus automatically creates a Deployment and a Service in target/kubernetes/. This saves you from writing YAML by hand and ensures that the manifests are consistent with your application’s configuration.

You can also add both to an existing Quarkus project with the Quarkus CLI:

quarkus extension add container-image-jib kubernetes

With them in place, your project knows how to build an image and describe how that image should run inside Kubernetes.

Step 2. Configure the container image

By default, Quarkus will build a container image with a generic name. But in real projects, images need to have meaningful names and versions. This is especially true when you push them to a container registry (like Quay.io or Docker Hub) so that Kubernetes can pull them later.

Quarkus uses three simple properties to define the image:

  • quarkus.container-image.group which is usually your container registry username or organization.
  • quarkus.container-image.name which is the application name, often the same as your project.
  • quarkus.container-image.tag which is the version, which helps you keep track of releases.

Add these to src/main/resources/application.properties:

quarkus.container-image.group=myuser
quarkus.container-image.name=getting-started
quarkus.container-image.tag=1.0.0

Only replace myuser with your user name if you plan to push the image to your container registry such as Quay.io.

When you run the build later, Quarkus will use this information to create an image named:

myuser/getting-started:1.0.0

This naming convention is important because it allows Kubernetes to find and run the correct version of your application.

Step 3. Build the container image

Building a container image is more than just packaging your code. The image is what Kubernetes (or any container runtime) runs. Quarkus integrates tightly with Jib to build efficient images. Jib doesn’t just create a single “big file.” Instead, it builds layered images. This means:

  • One layer contains your application dependencies (all JAR files your app uses).
  • Another layer contains your compiled classes.
  • Another layer contains your configuration and resources.

Why is this important? If you only change your code but not your dependencies, Jib can reuse the dependency layer from a previous build. That makes rebuilding much faster and keeps images smaller. This layering is one reason Quarkus builds feel lightweight compared to traditional Java apps.

Now build the image:

./mvnw package -Dquarkus.container-image.build=true

Quarkus will:

  • Compile your project.
  • Use Jib to assemble the container image with layers.
  • Tag the image with the values from application.properties.
  • Generate Kubernetes manifests in target/kubernetes/.

List your local images:

podman images

You should be able to see the image localhost/myuser/getting-started with tag 1.0.0 listed in the output.

You can also inspect the generated Kubernetes manifest:

ls target/kubernetes/

You should see:

kubernetes.yml

This file contains a Deployment and a Service that describe how your Quarkus app runs in Kubernetes.

By building images this way, you get reproducible, optimized containers without writing Dockerfiles. Jib ensures that your builds are fast, efficient, and friendly to CI/CD pipelines.

Step 4. Run the image locally

The newly create localhost/myuser/getting-started:1.0.0 image can be run locally using podman with the following command.

podman run -d -p 8080:8080 localhost/myuser/getting-started:1.0.0

Note: If you see a message such as WARNING: image platform (linux/amd64) does not match the expected platform (linux/arm64) (usually in MacOS), remove the current container, and rebuild the local image for the current platform.

podman rm -f $(podman ps -q --filter ancestor=localhost/myuser/getting-started:1.0.0)

./mvnw package -Dquarkus.container-image.build=true -Dquarkus.jib.platforms=linux/arm64

finally, run the image using the following command

podman run -d -p 8080:8080 localhost/myuser/getting-started:1.0.0

You can view the output from the terminal by executing

curl http://localhost:8080/hello

Make sure to stop the container as shown below to prevent conflicts while running other applications on port 8080.

podman rm -f $(podman ps -q --filter ancestor=localhost/myuser/getting-started:1.0.0)

Step 5. Deploy your app to Kubernetes (Optional)

In this step, we point you to a full deployment walkthrough. If you don't have a cluster yet, you can use Minikube locally (for example with Podman Desktop) or try the OpenShift Developer Sandbox.

Building a container image is only half the story. To run your application in Kubernetes you need to define how it should run. Kubernetes uses YAML manifests for resources such as:

  • Deployment — How to run your app: container image, number of replicas, and restart policies. If a pod crashes, the Deployment starts a new one.
  • Service — How to expose the app inside (and sometimes outside) the cluster. A Service gives your pods a stable name and load-balances traffic across replicas.

Quarkus generates these manifests for you from your configuration, so you get a solid starting point without writing YAML by hand.

follow the full tutorial: Deploy a Quarkus application to Kubernetes. It walks you through:

  • Setting up Minikube and building images with Jib
  • Deploying your app (and optionally PostgreSQL) with configuration via ConfigMap
  • Exposing the app and adding liveness and readiness probes

Everything is driven by application.properties and Quarkus extensions; you don't have to write YAML for the app itself. When you're ready, apply the generated manifest to your cluster (for example, kubectl apply -f target/kubernetes/kubernetes.yml or the Minikube variant), then use kubectl port-forward to access the app. The tutorial has the exact commands and next steps.

Summary

You learned how Quarkus simplifies containerization by using Jib to build layered container images without Dockerfiles, and how the Kubernetes extension automatically generates Deployment and Service manifests based on your application configuration. This convention-over-configuration approach eliminates the need to write YAML manually and ensures that your containerized applications are optimized for Kubernetes deployments with minimal effort.