Quarkus #
Quarkus adalah framework Java yang dirancang untuk Kubernetes-native dan GraalVM native image. Dengan startup time yang super cepat dan memory footprint yang kecil, Quarkus menjadi pilihan utama untuk aplikasi cloud-native. Docker Compose memungkinkan developer menjalankan Quarkus dengan dependency-nya (database, cache) dalam satu environment terisolasi.
Artikel ini membahas setup Quarkus dengan Docker Compose untuk local development.
Prasyarat #
- Docker dan Docker Compose versi terbaru
- Java 21+ untuk development
- Maven atau Gradle
Project Quarkus standar (dari code.quarkus.io atau mvn io.quarkus.platform:quarkus-maven-plugin:3.6.4:create):
quarkus-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ └── resources/
│ └── test/
├── pom.xml
└── mvnw
Dockerfile untuk Quarkus #
Quarkus punya Docker build tooling built-in yang menghasilkan Dockerfile optimal. Atau kamu bisa tulis manual.
Menggunakan Quarkus build tooling (recommended):
# Tambahkan extension container-image
./mvnw quarkus:add-extension -Dextensions="container-image-docker"
# Build image
./mvnw package -DskipTests -Dquarkus.container-image.build=true
Quarkus otomatis menghasilkan Dockerfile dan build image dengan tag sesuai konfigurasi.
Dockerfile manual (multi-stage):
# syntax=docker/dockerfile:1.6
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY pom.xml mvnw ./
COPY .mvn .mvn
RUN chmod +x mvnw && ./mvnw dependency:go-offline
COPY src ./src
RUN ./mvnw package -DskipTests
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/quarkus-app/ /app/
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/quarkus-run.jar"]
Dockerfile untuk native build (GraalVM):
FROM ghcr.io/graalvm/graalvm-ce:java21-22.3.0 AS builder
WORKDIR /app
COPY pom.xml mvnw ./
COPY .mvn .mvn
RUN chmod +x mvnw && ./mvnw dependency:go-offline
COPY src ./src
RUN ./mvnw package -DskipTests -Pnative
FROM alpine:3.19
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY --from=builder /app/target/quarkus-app /app/quarkus-app
EXPOSE 8080
ENTRYPOINT ["/app/quarkus-app"]
Native image startup dalam ~15ms dan memory ~30MB.
docker-compose.yml untuk Development #
services:
app:
build:
context: .
dockerfile: Dockerfile
target: builder
image: quarkus-app:dev
container_name: quarkus-app
command: ./mvnw quarkus:dev
volumes:
- ./src:/app/src
- ./pom.xml:/app/pom.xml
- target:/app/target
ports:
- "8080:8080"
- "5005:5005" # debug port
environment:
- QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://db:5432/quarkus
- QUARKUS_DATASOURCE_USERNAME=app
- QUARKUS_DATASOURCE_PASSWORD=dev
- QUARKUS_REDIS_HOSTS=redis://cache:6379
- JAVA_ENABLE_DEBUG=true
- JAVA_DEBUG=true
depends_on:
db:
condition: service_healthy
cache:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
- POSTGRES_USER=app
- POSTGRES_PASSWORD=dev
- POSTGRES_DB=quarkus
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d quarkus"]
interval: 10s
timeout: 5s
retries: 5
ports:
- "5432:5432"
cache:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
ports:
- "6379:6379"
volumes:
db-data:
target:
Quarkus Dev Mode #
Perintah ./mvnw quarkus:dev mengaktifkan Quarkus Dev Mode yang powerful:
- Live reload — perubahan source code trigger restart dalam <1 detik
- Continuous testing — test dijalankan otomatis saat source code berubah
- Dev UI — UI interaktif di http://localhost:8080/q/dev/
- Database migration — otomatis run saat startup
- Dev Services — otomatis spin up service (Postgres, Redis, Kafka) via Testcontainers saat tidak ada
Quarkus Dev Services sangat powerful. Jika kamu tidak define quarkus.datasource.db-kind atau connection detail di profile dev, Quarkus otomatis start Postgres container via Testcontainers untuk development. Ini berarti Compose file untuk service eksternal bisa minimal.
Quarkus Dev UI #
Dev UI adalah web-based UI untuk Quarkus dev mode.
Akses di http://localhost:8080/q/dev/. Fitur:
- Extensions — list installed extensions, lihat config
- Configuration — lihat runtime config, edit dev-only config
- Endpoints — list JAX-RS endpoints
- Database — browse entities, run queries
- Continuous Testing — lihat test yang lagi jalan
- Dev Services — lihat service yang auto-started
Database dengan Hibernate ORM dan Panache #
Quarkus + Hibernate ORM + Panache adalah combo powerful untuk database access.
application.properties:
# Database
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=app
quarkus.datasource.password=dev
quarkus.datasource.jdbc.url=jdbc:postgresql://db:5432/quarkus
# Hibernate
quarkus.hibernate-orm.database.generation=update
quarkus.hibernate-orm.log.sql=true
Entity:
@Entity
public class User extends PanacheEntity {
public String email;
public String name;
public static List<User> findByEmail(String email) {
return find("email", email).list();
}
}
Repository:
@ApplicationScoped
public class UserRepository {
@Inject
EntityManager em;
public List<User> findAll() {
return em.createQuery("FROM User", User.class).getResultList();
}
public Optional<User> findById(Long id) {
return Optional.ofNullable(em.find(User.class, id));
}
@Transactional
public User save(User user) {
em.persist(user);
return user;
}
}
Untuk dev, quarkus.hibernate-orm.database.generation=update otomatis update schema. Untuk production, pakai Flyway atau Liquibase.
Health Check dan Metrics #
Quarkus punya extension untuk health dan metrics built-in.
application.properties:
quarkus.smallrye-health.root-path=/q/health
quarkus.micrometer.export.prometheus.path=/q/metrics
Endpoint:
/q/health/live— liveness probe/q/health/ready— readiness probe/q/health/started— startup probe/q/metrics— Prometheus metrics
Testing dengan Testcontainers #
Quarkus testing bisa pakai Testcontainers otomatis.
UserResourceTest.java:
@QuarkusTest
class UserResourceTest {
@Test
void shouldListUsers() {
given()
.when().get("/users")
.then()
.statusCode(200)
.body("size()", is(0));
}
@Test
void shouldCreateUser() {
given()
.contentType(ContentType.JSON)
.body("{\"email\":\"[email protected]\",\"name\":\"Test\"}")
.when().post("/users")
.then()
.statusCode(201);
}
}
Quarkus Dev Services otomatis spin up Postgres container untuk test, jadi tidak perlu Compose file khusus.
Build dan Run #
# Build
docker compose build
# Jalankan
docker compose up -d
# Lihat log
docker compose logs -f app
# Stop
docker compose down
Akses:
- App: http://localhost:8080
- Dev UI: http://localhost:8080/q/dev/
- Postgres: localhost:5432
- Redis: localhost:6379
Best Practice #
Pakai Dev Services untuk Dependency #
Untuk development, Dev Services otomatis manage container Postgres/Redis/Kafka. Compose file bisa lebih minimal.
Native Image untuk Production #
Quarkus + GraalVM native image ideal untuk production: startup ~15ms, memory ~30MB, image kecil.
Health Endpoints #
Konfigurasikan liveness, readiness, dan started probes untuk Kubernetes. Quarkus otomatis.
Database Migration Tool #
Untuk production, pakai Flyway. Untuk dev, update mode cukup.
Resource Limits #
services:
app:
deploy:
resources:
limits:
memory: 512M
Native image hemat memory. JVM mode butuh lebih banyak.
Quarkus dengan Kubernetes (k8s) di Lokal #
Quarkus punya ekstensi untuk deploy ke Kubernetes secara otomatis.
./mvnw quarkus:add-extension -Dextensions="kubernetes"
application.properties:
quarkus.kubernetes.deploy=true
quarkus.kubernetes.image-name=quarkus-app
quarkus.kubernetes.image-tag=1.0.0
quarkus.kubernetes.replicas=3
Build akan otomatis apply ke Kubernetes cluster yang sedang aktif. Untuk testing lokal, pakai kind atau minikube.
Quarkus dengan GraalVM Native di CI/CD #
Untuk build native image di CI/CD, Quarkus mendukung build di container.
./mvnw package -DskipTests \
-Pnative \
-Dquarkus.native.container-build=true
Quarkus otomatis pull image quay.io/quarkus/ubi-quarkus-native-image:21.3.0-java17 dan run native build di dalam container. Tidak perlu install GraalVM di host.
Reactive Quarkus dengan Mutiny #
Quarkus menggunakan Mutiny untuk reactive programming.
@GET
@Path("/users")
public Uni<List<User>> listUsers() {
return User.listAll(); // returns Uni
}
@GET
@Path("/users/{id}")
public Uni<User> getUser(@PathVariable Long id) {
return User.findById(id)
.onItem().ifNull().failWith(() -> new NotFoundException());
}
Mutiny lebih ergonomis dari RxJava atau Reactor untuk developer Quarkus.
Quarkus CLI #
Quarkus punya CLI resmi yang mempermudah project management.
# Install Quarkus CLI
sdk install quarkus
# Create project
quarkus create app my-app
# Add extension
quarkus extension add hibernate-orm-panache
# Dev mode (with Tilt/docker-compose integration)
quarkus dev
quarkus dev otomatis detect perubahan, restart, dan bisa langsung deploy ke k8s.
Reaktif Database dengan Reactive Hibernate #
Untuk workload reactive, Quarkus punya Hibernate Reactive.
quarkus.hibernate-orm.database.generation=update
quarkus.datasource.reactive.url=postgresql://db:5432/quarkus
@GET
@Path("/users")
public Uni<List<User>> listUsers() {
return User.<User>listAll(Sort.by("name"));
}
Reactive Hibernate pakai driver async (vertx-pg-client) untuk non-blocking database access.
Scheduled Tasks #
Quarkus support scheduled tasks.
@ApplicationScoped
public class CleanupTask {
@Scheduled(every = "1h", identity = "cleanup-task")
void cleanup() {
// run setiap jam
// mis. hapus session expired
}
@Scheduled(cron = "0 0 2 * * ?")
void dailyReport() {
// run jam 2 pagi setiap hari
}
}
Scheduled task berjalan di scheduler thread Quarkus. Aman di-run di container dengan multiple replicas — Quarkus pakai leader election untuk mencegah duplikat.
OpenTelemetry Tracing #
quarkus.otel.enabled=true
quarkus.otel.traces.exporter=otlp
quarkus.otel.exporter.otlp.traces.endpoint=http://jaeger:4317
Quarkus otomatis instrument HTTP, JDBC, dan lain-lain. Span dikirim ke Jaeger atau platform lain.
Recap Cheatsheet #
| Pattern | Quarkus Extension |
|---|---|
| Database | hibernate-orm-panache, jdbc-postgresql |
| Cache | redis-client |
| REST | resteasy-reactive-jackson |
| Reactive | mutiny, hibernate-reactive |
| Health | smallrye-health |
| Metrics | micrometer-registry-prometheus |
| Tracing | opentelemetry |
| Native | native profile |
| Kubernetes | kubernetes |
| Testing | junit5, rest-assured |
Ringkasan #
- Quarkus ideal untuk local development dengan startup time dan memory footprint yang kecil.
- Quarkus dev mode dengan
quarkus:devpunya live reload, continuous testing, dan Dev UI.- Dev Services otomatis spin up Postgres/Redis/Kafka via Testcontainers saat dependency tidak didefinisikan.
- Multi-stage Dockerfile dengan builder stage (JDK + Maven) dan runtime stage (JRE + JAR).
- Native image dengan GraalVM untuk production: startup ~15ms, memory ~30MB, image kecil.
- Hibernate ORM + Panache untuk database access dengan pattern repository.
- Health endpoints built-in:
/q/health/live,/q/health/ready,/q/health/started.- Testcontainers otomatis spun up untuk test.
- Configuration via
application.propertiesdengan Quarkus config (prefixquarkus.).- Best practice: Dev Services untuk dep, native image untuk prod, Flyway untuk migration, resource limits sesuai mode (JVM vs native).
- Build tooling Quarkus otomatis menghasilkan Dockerfile optimal via
container-image-dockerextension.- Debugging dengan
JAVA_DEBUG=trueenvironment dan port 5005 di-expose.- Dev UI di
/q/dev/untuk interaksi dengan extensions, config, dan database.