Quarkus Topic
Part 1: Creating Native Executables with GraalVM
Native compilation is one of Quarkus's killer features, producing ultra-fast, low-memory executables.
GraalVM Setup
Option 1: Install GraalVM locally
bash
# Download GraalVM from https://www.graalvm.org/ # Set GRAALVM_HOME environment variable export GRAALVM_HOME=/path/to/graalvm
Option 2: Use Quarkus with Mandrel (recommended)
xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-native-image</artifactId>
</dependency>
Native Build Configuration
properties
# application.properties - Native build configuration quarkus.package.type=native quarkus.native.enabled=true # Native image optimization quarkus.native.container-build=true quarkus.native.java-version=17 # Memory settings for native build quarkus.native.native-image-xmx=4g # Reflection configuration (auto-detected in most cases) quarkus.native.enable-all-security-services=true quarkus.native.add-all-charsets=true
Building Native Executables
bash
# Build native executable using local GraalVM ./mvnw package -Dnative # Build native executable in container (no local GraalVM needed) ./mvnw package -Dnative -Dquarkus.native.container-build=true # For Podman instead of Docker ./mvnw package -Dnative -Dquarkus.native.container-build=true -Dquarkus.native.container-runtime=podman # Build using specific builder image ./mvnw package -Dnative -Dquarkus.native.container-build=true \ -Dquarkus.native.builder-image=quay.io/quarkus/ubi-quarkus-mandrel:22.3-java17
Native-Specific Configuration
java
// Register classes for reflection (when auto-detection fails)
@RegisterForReflection(targets = {
MyCustomClass.class,
AnotherDTO.class
})
public class ReflectionConfiguration {
}
// Or register at class level
@RegisterForReflection
public class MyCustomClass {
private String data;
// getters/setters
}
Testing Native Executables
bash
# Build and run native executable ./mvnw package -Dnative ./target/my-app-1.0.0-runner # Test the native application curl http://localhost:8080/api/hello
Part 2: Building Docker Images
Quarkus provides multiple strategies for containerizing applications.
Docker Configuration
properties
# application.properties - Docker image configuration quarkus.container-image.build=true quarkus.container-image.group=mycompany quarkus.container-image.name=my-quarkus-app quarkus.container-image.tag=1.0.0 quarkus.container-image.registry=quay.io # Using JVM mode (balanced performance/startup) quarkus.container-image.builder=jib quarkus.jib.base-jvm-image=eclipse-temurin:17-jre # Using Native mode (best startup/memory) quarkus.package.type=native quarkus.native.container-build=true quarkus.container-image.builder=docker
Different Containerization Strategies
1. Using Jib (Recommended for JVM)
properties
# Jib configuration for JVM container quarkus.container-image.build=true quarkus.container-image.builder=jib quarkus.jib.base-jvm-image=eclipse-temurin:17-jre-alpine quarkus.jib.jvm-arguments=-Djava.util.logging.manager=org.jboss.logmanager.LogManager,-Xmx64m
2. Using Docker (for Native)
properties
# Docker configuration for native container quarkus.container-image.build=true quarkus.container-image.builder=docker quarkus.native.container-build=true
3. Using Buildpacks
properties
# Cloud Native Buildpacks quarkus.container-image.build=true quarkus.container-image.builder=buildpacks quarkus.container-image.group=myorg
Custom Dockerfile Support
src/main/docker/Dockerfile.jvm
dockerfile
FROM eclipse-temurin:17-jre-alpine WORKDIR /work/ COPY target/*-runner.jar app.jar RUN chown 1001:1001 app.jar USER 1001 EXPOSE 8080 CMD ["java", "-jar", "app.jar"]
src/main/docker/Dockerfile.native
dockerfile
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.6 WORKDIR /work/ COPY target/*-runner /work/application RUN chown 1001:1001 /work/application USER 1001 EXPOSE 8080 CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
src/main/docker/Dockerfile.native-micro
dockerfile
# Micro Docker image for native executable FROM quay.io/quarkus/quarkus-micro-image:2.0 WORKDIR /work/ COPY target/*-runner /work/application RUN chmod 775 /work EXPOSE 8080 CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
Building Container Images
bash
# Build JVM container image ./mvnw clean package -Dquarkus.container-image.build=true # Build native container image ./mvnw clean package -Dnative -Dquarkus.container-image.build=true # Push to registry ./mvnw clean package -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true # Build with custom properties ./mvnw clean package \ -Dquarkus.container-image.build=true \ -Dquarkus.container-image.group=mycompany \ -Dquarkus.container-image.name=myapp \ -Dquarkus.container-image.tag=v1.0.0
Part 3: Deploying to Various Platforms
Kubernetes Deployment
Dependencies
xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-kubernetes</artifactId>
</dependency>
<!-- For OpenShift -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-openshift</artifactId>
</dependency>
Kubernetes Configuration
properties
# application.properties - Kubernetes configuration quarkus.kubernetes.deploy=true quarkus.kubernetes.deployment-target=kubernetes # Application metadata quarkus.application.name=my-quarkus-app quarkus.application.version=1.0.0 # Container configuration quarkus.container-image.group=my-namespace quarkus.container-image.registry=my-registry.com quarkus.container-image.username=$REGISTRY_USER quarkus.container-image.password=$REGISTRY_PASSWORD # Kubernetes resources quarkus.kubernetes.replicas=3 quarkus.kubernetes.labels.app=my-quarkus-app quarkus.kubernetes.annotations.priority=high # Service configuration quarkus.kubernetes.service-type=ClusterIP quarkus.kubernetes.ports.http=8080 # Health checks quarkus.kubernetes.liveness-probe.http-action-path=/q/health/live quarkus.kubernetes.readiness-probe.http-action-path=/q/health/ready # Resource limits (for native) quarkus.kubernetes.resources.limits.memory=64Mi quarkus.kubernetes.resources.limits.cpu=500m quarkus.kubernetes.resources.requests.memory=32Mi quarkus.kubernetes.resources.requests.cpu=100m
Custom Kubernetes Resources
java
@KubernetesClient
@ServiceAccount
@Ingress(path="/")
@RoleBinding(roleRefName = "view", subjects = @Subject(kind = "ServiceAccount", name = "my-service-account"))
public class MyAppKubernetesConfig {
// Kubernetes resources will be generated automatically
}
OpenShift Deployment
properties
# OpenShift specific configuration quarkus.openshift.deploy=true quarkus.openshift.expose=true quarkus.openshift.route.expose=true quarkus.openshift.annotations.openshift.io/display-name=My Quarkus App # S2I (Source-to-Image) build quarkus.openshift.build-strategy=docker quarkus.container-image.builder=docker
AWS Lambda Deployment
Dependencies
xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-lambda</artifactId>
</dependency>
<!-- For HTTP via API Gateway -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-lambda-http</artifactId>
</dependency>
<!-- For RESTEasy Reactive -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-amazon-lambda-rest</artifactId>
</dependency>
Lambda Configuration
properties
# AWS Lambda configuration quarkus.lambda.handler=test quarkus.native.container-build=true # For HTTP Lambda quarkus.lambda.http.enabled=true # Deployment configuration quarkus.container-image.registry=your-account-id.dkr.ecr.us-east-1.amazonaws.com quarkus.container-image.name=my-lambda-function
Lambda Handler
java
public class LambdaHandler implements RequestHandler<APIGatewayV2HTTPEvent, APIGatewayV2HTTPResponse> {
private static final QuarkusHttpHandler handler = QuarkusHttpHandlerSupplier.get();
@Override
public APIGatewayV2HTTPResponse handleRequest(APIGatewayV2HTTPEvent event, Context context) {
return handler.handleRequest(event, context);
}
}
// Or for simple functions
public class SimpleLambdaHandler implements RequestHandler<InputObject, OutputObject> {
@Override
public OutputObject handleRequest(InputObject input, Context context) {
return processInput(input);
}
}
Deploying to AWS Lambda
bash
# Build native image for Lambda ./mvnw clean package -Dnative -Dquarkus.native.container-build=true # Deploy using SAM (Serverless Application Model) sam deploy --template-file target/sam.jvm.yaml --stack-name my-quarkus-app # Or using AWS CDK cdk deploy
Azure Functions Deployment
Dependencies
xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-azure-functions</artifactId>
</dependency>
Azure Configuration
properties
quarkus.azure-functions.auth-level=anonymous quarkus.package.type=native
Part 4: Quarkus Dev Services
Dev Services automatically provide dev-mode containers for databases, message brokers, and other services.
How Dev Services Works
Dev Services automatically:
-
Detects needed services from dependencies
-
Starts containers in development/test mode
-
Configures your application to connect to them
-
Tears down containers when no longer needed
Database Dev Services
PostgreSQL
properties
# No configuration needed! Dev Services auto-starts PostgreSQL quarkus.datasource.db-kind=postgresql quarkus.datasource.devservices.enabled=true quarkus.datasource.devservices.port=5432 # Optional: use specific image quarkus.datasource.devservices.image-name=postgres:14
MySQL
properties
quarkus.datasource.db-kind=mysql quarkus.datasource.devservices.enabled=true
Message Broker Dev Services
Redis
xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-redis-client</artifactId>
</dependency>
properties
# Auto-starts Redis container quarkus.redis.devservices.enabled=true quarkus.redis.hosts=redis://localhost:6379
Kafka
xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-messaging-kafka</artifactId>
</dependency>
properties
# Auto-starts Kafka + ZooKeeper containers quarkus.kafka.devservices.enabled=true quarkus.kafka.devservices.port=9092
Other Dev Services
Mail Server (TestMail)
properties
quarkus.mailer.devservices.enabled=true quarkus.mailer.port=25
Keycloak (for OAuth2 testing)
properties
quarkus.keycloak.devservices.enabled=true quarkus.oidc.auth-server-url=http://localhost:8080/auth/realms/quarkus
Custom Dev Services Configuration
properties
# Control Dev Services behavior quarkus.datasource.devservices.reuse=true # Reuse containers between runs quarkus.datasource.devservices.shared=true # Share between multiple apps # Resource limits quarkus.datasource.devservices.memory=1G quarkus.kafka.devservices.service-kafka-node-count=2 # Multiple brokers
Dev Services in Action
When you run ./mvnw quarkus:dev, you'll see output like:
text
Dev Services for PostgreSQL started. Other applications can connect using: - jdbc:postgresql://localhost:5432/quarkus
Testing with Dev Services
java
@QuarkusTest
@TestResource(MyTestResource.class)
public class DatabaseTest {
@Test
public void testWithDevDatabase() {
// Tests automatically use the Dev Services database
given()
.when().get("/api/users")
.then()
.statusCode(200);
}
}
// Custom test resource
public class MyTestResource implements QuarkusTestResourceLifecycleManager {
@Override
public Map<String, String> start() {
// Custom test container setup
return Collections.singletonMap("quarkus.datasource.jdbc.url",
"jdbc:postgresql://localhost:5432/testdb");
}
@Override
public void stop() {
// Cleanup
}
}
Part 5: Cloud-Native Best Practices
Health Checks
java
@Liveness
@ApplicationScoped
public class CustomLivenessCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("Custom live check");
}
}
@Readiness
@ApplicationScoped
public class CustomReadinessCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("Custom ready check");
}
}
Configuration for Different Environments
properties
# application.properties - Base configuration
quarkus.application.name=my-app
quarkus.http.port=8080
# %dev - Development
%dev.quarkus.log.level=DEBUG
%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/devdb
# %test - Testing
%test.quarkus.log.level=INFO
%test.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/testdb
# %prod - Production
%prod.quarkus.log.level=WARN
%prod.quarkus.datasource.jdbc.url=${DATABASE_URL:jdbc:postgresql://prod-db:5432/proddb}
%prod.quarkus.datasource.username=${DB_USERNAME}
%prod.quarkus.datasource.password=${DB_PASSWORD}
Deployment Scripts
deploy-to-k8s.sh
bash
#!/bin/bash # Build and deploy to Kubernetes echo "Building native image..." ./mvnw clean package -Dnative -Dquarkus.container-image.build=true echo "Pushing to registry..." ./mvnw package -Dquarkus.container-image.push=true echo "Deploying to Kubernetes..." kubectl apply -f target/kubernetes/kubernetes.yml echo "Rolling update..." kubectl rollout restart deployment/my-quarkus-app
Key Takeaways
-
Native First: Always consider native compilation for cloud deployment
-
Dev Services: Eliminates manual setup for development databases/message brokers
-
Multi-Platform: Quarkus supports Kubernetes, OpenShift, AWS Lambda, Azure Functions
-
Optimized Containers: Tiny images with fast startup perfect for microservices
-
Configuration Profiles: Easy environment-specific configuration
-
Automated Deployments: Streamlined CI/CD with container-first approach
Quarkus makes cloud deployment incredibly smooth with its container-native approach, fast startup times, and comprehensive cloud integration features.
Comments (0)
No comments yet. Be the first to comment!