Generated banner for Quarkus Native And Container
Generated logo for Quarkus Native And Container

Quarkus Native And Container

GitHubOfficialFirst committed by jduboisDistributed by GitHub

  • Skill
  • Tool integration
  • Software development
  • MIT
  • No issues found

From the author

Build Quarkus native executables (Mandrel/GraalVM), fix native failures with reflection registration, test the native binary, and produce container images and Kubernetes/OpenShift manifests. Use for native, Docker, Jib or Kubernetes work in a Quarkus project.
— the description by jdubois

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a comprehensive workflow for compiling Quarkus applications into native executables using Mandrel or GraalVM. It covers the build process, troubleshooting common native-image failures such as reflection and resource registration, testing native binaries with integration tests, and generating container images and Kubernetes or OpenShift manifests for deployment.

What it does

  • Builds native executables using Maven or Gradle with Mandrel or GraalVM.
  • Configures reflection and resource registration to resolve common native-image runtime errors.
  • Executes black-box integration tests against native binaries.
  • Generates container images using Jib or Docker/Podman.
  • Produces and customizes Kubernetes and OpenShift deployment manifests.
  • Manages build-time vs. run-time class initialization settings.

When to use it

  • When you need to optimize Quarkus application startup time and memory footprint.
  • When preparing a Quarkus application for production deployment in containerized environments.
  • When encountering ClassNotFoundException or initialization errors during native compilation.
  • When automating the generation of Kubernetes or OpenShift deployment configurations.

Advantages

  • Reduces application startup time and memory usage significantly.
  • Simplifies the transition from JVM-based development to native production builds.
  • Provides clear patterns for handling reflection and dynamic class loading in native mode.
  • Integrates directly with standard build tools like Maven and Gradle.

Usage examples

“How do I build a native executable for my Quarkus project using Maven?”
The agent provides the command ./mvnw package -Dnative to trigger the native build process using the configured Mandrel or GraalVM environment.
“My native build fails with a ClassNotFoundException. How do I fix it?”
The agent explains how to use @RegisterForReflection or a reflection-config.json file to explicitly register classes for native-image compilation.
“How can I generate Kubernetes manifests for my Quarkus app?”
The agent instructs you to add the kubernetes extension and explains how to use properties like quarkus.kubernetes.replicas to customize the generated YAML.
“How do I test my native binary?”
The agent shows how to use @QuarkusIntegrationTest and the ./mvnw verify -Dnative command to run integration tests against the native runner.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/github/quarkus-native-and-container/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip quarkus-native-and-container.zip -d .agents/skills

Documentation by jdubois

Quarkus Native and Container

Check the project's Quarkus version first. For generic (non-Quarkus) GraalVM work, use the optional java-add-graalvm-native-image-support skill if installed (otherwise see the GraalVM docs, https://www.graalvm.org/latest/reference-manual/native-image/).

Native build

# container build: no local GraalVM needed (Docker/Podman required)
./mvnw package -Dnative -Dquarkus.native.container-build=true
# local Mandrel/GraalVM (JAVA_HOME / GRAALVM_HOME must point to it)
./mvnw package -Dnative
# Gradle, Quarkus 3.10+ (add -Dquarkus.native.container-build=true without a local Mandrel)
./gradlew build -Dquarkus.native.enabled=true -Dquarkus.package.jar.enabled=false
# Gradle, older Quarkus
./gradlew build -Dquarkus.package.type=native

quarkus.package.type was deprecated in 3.10 (the 3.10 migration guide replaces it with quarkus.native.enabled and quarkus.package.jar.*); it is still accepted in 3.40 with a warning. Version gate verified with Gradle: on 3.9.5 -Dquarkus.native.enabled=true -Dquarkus.package.jar.enabled=false is ignored ("Unrecognized configuration key" warnings) and only a JVM quarkus-app is built, while -Dquarkus.package.type=native produces the native runner; on 3.10.0, 3.27.6 and 3.40.1 the new keys produce the native runner (3.10.0 also accepts the old key with the deprecation warning). The Maven native profile in the generated pom.xml already sets quarkus.native.enabled=true, quarkus.package.jar.enabled=false and skipITs=false when -Dnative is passed.

Local build verified on macOS arm64 with the Mandrel tarball for your Quarkus line from https://github.com/graalvm/mandrel/releases (mandrel-java25-macos-aarch64-25.0.4.1-Final.tar.gz for 3.40.1, extracted anywhere, JAVA_HOME pointing at its Contents/Home; Xcode command line tools are enough): 3.40.1 Maven package -Dnative took about 70 s and Gradle build with the two flags about 2.5 min; the runner is a Mach-O executable that starts in about 0.04 s, and ./mvnw verify -Dnative ran the *IT against it successfully. Quarkus checks the Mandrel/GraalVM version: 3.40 refuses 23.1 ("Out of date version of GraalVM or Mandrel detected ... Quarkus currently supports 25.0.0"), so use Mandrel 25 with 3.40 and mandrel-java21-macos-aarch64-23.1.12.1-Final with 3.27.6 (Maven verify -Dnative and Gradle both verified there).

Binary: target/*-runner (Maven) or build/*-runner (Gradle). A container build on macOS or Windows produces a Linux ELF that cannot run on the host: run it in a Linux container (for example docker run -v "$PWD/target:/w:ro" registry.access.redhat.com/ubi9/ubi-minimal /w/<name>-runner with the datasource passed through QUARKUS_DATASOURCE_* env vars), and note that ./mvnw verify -Dnative then fails in the *IT with Exit code is: '126'. Mandrel is Red Hat's GraalVM distribution for Quarkus; the container build pulls a Mandrel builder image matching the project (3.40.1 used quay.io/quarkus/ubi9-quarkus-mandrel-builder-image:jdk-25, Mandrel 25.0.4.1, about 2.5 minutes including the image pull); override it with quarkus.native.builder-image if needed. Native builds are slow and memory-hungry (several GB); do them in CI or on demand, not on every test run.

Common native failures

SymptomFix
ClassNotFoundException / NoSuchMethodException at runtime (reflection, JSON serialization of DTOs)annotate with @RegisterForReflection (or @RegisterForReflection(targets = ...) on a holder class for third-party types), or put a reflection-config.json in src/main/resources and set quarkus.native.additional-build-args=-H:ReflectionConfigurationFiles=reflection-config.json
Missing resource filesquarkus.native.resources.includes=templates/**
Library not supporting nativelook for a Quarkus extension, or choose another library
Class initialized at build time breaks--initialize-at-run-time=... through quarkus.native.additional-build-args
OutOfMemoryError during buildraise container memory or quarkus.native.native-image-xmx
Dynamic proxies / serializationregister via annotations or extension
@RegisterForReflection(targets = ExternalDto.class)
public record ProductDto(String name) {}

Prefer Quarkus extensions (they register reflection automatically) over raw libraries. Verified: a Panache + Quarkus REST app built natively and served JSON with a record DTO; Quarkus REST registers returned types itself, so @RegisterForReflection is mainly needed for types reached only reflectively (custom serialization, third-party types). Both rows were reproduced on 3.40.1 (local Mandrel 25): a resource calling Class.forName("org.acme.Hidden").getDeclaredConstructor().newInstance() returned HTTP 500 ClassNotFoundException: org.acme.Hidden in the native binary, and worked after adding src/main/resources/reflection-config.json ([{ "name": "org.acme.Hidden", "allDeclaredConstructors": true }]) with the documented -H:ReflectionConfigurationFiles=reflection-config.json (the relative file name resolves from src/main/resources). For the run-time initialization row, a static final java.util.Random in a class forced to build-time init (--initialize-at-build-time=org.acme.Holder) failed the build with "Detected an instance of Random/SplittableRandom class in the image heap ... mark it explicitly for run time initialization with '--initialize-at-run-time=<culprit>'"; switching to --initialize-at-run-time=org.acme.Holder fixed it, also combined with the reflection flag in one comma-separated quarkus.native.additional-build-args. Quarkus's generated native-image feature calls RuntimeClassInitialization.initializeAtBuildTime("") and then applies explicit run-time overrides, so classes default to build-time initialization. Your own static initializers (random seeds, clocks, env reads, threads) can therefore cause this failure too, not only libraries.

Test the native binary

@QuarkusIntegrationTest
class GreetingResourceIT extends GreetingResourceTest {}
./mvnw verify -Dnative

@QuarkusIntegrationTest black-box tests run in the verify phase (Failsafe) against the native binary; no CDI injection.

Container images

quarkus extension add container-image-jib      # or container-image-docker
./mvnw package -Dquarkus.container-image.build=true
./mvnw package -Dnative -Dquarkus.native.container-build=true -Dquarkus.container-image.build=true

container-image-jib needs no Docker daemon to push: with DOCKER_HOST pointing at a non-existent socket, ./mvnw package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true -Dquarkus.container-image.registry=localhost:5055 -Dquarkus.container-image.insecure=true -Dquarkus.container-image.group=acme pushed acme/q340m:1.0.0-SNAPSHOT to a local registry:2 (3.40.1, JVM image). Without push=true Jib loads the image into a local Docker/Podman and fails with Cannot get an executable name when no container runtime is available when none is reachable. A tar-only output was not found or tested; the pushed image was not run.

Dockerfiles for manual builds live in src/main/docker (Dockerfile.jvm, Dockerfile.native, Dockerfile.native-micro). Set quarkus.container-image.registry/group/name/tag, and -Dquarkus.container-image.push=true to push. Use pinned base-image tags and run as non-root.

Kubernetes / OpenShift

quarkus extension add kubernetes     # or: quarkus extension add openshift
./mvnw package

Manifests are generated in target/kubernetes/kubernetes.yml (and .json) for the kubernetes extension, and in target/kubernetes/openshift.yml for openshift. Customize via properties; the prefix follows the target (quarkus.kubernetes.* for Kubernetes, quarkus.openshift.* for OpenShift):

quarkus.kubernetes.replicas=2
quarkus.kubernetes.ingress.expose=true
quarkus.kubernetes.env.secrets=app-secrets
quarkus.kubernetes.resources.requests.memory=128Mi

The generated Deployment has no probes by default; with quarkus-smallrye-health installed it includes liveness, readiness and startup probes (/q/health/live, /q/health/ready, /q/health/started), and it sets envFrom.secretRef for env.secrets (verified on 3.40.1). Deploy with quarkus.kubernetes.deploy=true or kubectl apply -f target/kubernetes/kubernetes.yml. On OpenShift use the same properties under quarkus.openshift.*, expose the service with a Route via quarkus.openshift.route.expose=true (Kubernetes uses quarkus.kubernetes.ingress.expose=true instead), and apply with oc apply -f target/kubernetes/openshift.yml (or quarkus.openshift.deploy=true). Review generated YAML before applying; keep secrets out of it.

See also: native executables https://quarkus.io/guides/building-native-image; upgrades via quarkus update (https://quarkus.io/guides/update-quarkus); GraalVM release notes https://www.graalvm.org/release-notes/.

Files

Requirements and compatibility

Written for: GitHub Copilot

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

First committed by
GitHub avatar of jduboisjdubois
Publisher
GitHub (Official)
Distributed by
GitHub
Source
github/awesome-copilot · skills/quarkus-native-and-container · commit 797337f
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced
Contributors
jdubois

AutoGineer is not affiliated with or endorsed by jdubois or GitHub.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download quarkus-native-and-container.zip