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:dev punya 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.properties dengan Quarkus config (prefix quarkus.).
  • 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-docker extension.
  • Debugging dengan JAVA_DEBUG=true environment dan port 5005 di-expose.
  • Dev UI di /q/dev/ untuk interaksi dengan extensions, config, dan database.

← Sebelumnya: Spring Boot   Berikutnya: Micronaut →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact