Getting started with Quarkus
Quarkus – A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards. – is a container-first framework optimized for fast boot times and low memory consumption. The framework is build on top of many popular Java libraries and it provides support for building standard REST as well as reactive and message-driven microservices. Thanks to the fast startup times and low memory usage Quarkus can also be used to implement functions in serverless environment. Quarkus gives a lot of possibilities to develop apps faster thanks to unified configuration, amazing live reloading features and tooling support.
Learn how to get started with Quarkus and build a PetClinic REST API.
This blog post covers:
- Requirements for development environment
- Creating new project
- Developing, building and running the application with Java 11
- Datasource configuration with Postgres and Flyway
- CRUD service with pagination
- Creating integration tests
- Live reload and debugging
- Dockerizing the application (both native and non-native)
About PetClinic API
I decided to re-use the PetClinic model I used in this blog post Spring Boot and Spring Data REST.
Basically, it is a basic CRUD service for managing an imaginary PetClinic: pets, vets, visits etc.
Prerequisities
Docker
Docker will be used for running the dockerized version of the service itself but it will be also used to run the PostgreSQL server.
JDK 11 with GraalVM
The PetClinic API will be built with Java 11 therefore JDK 11 must be installed. For building native executables GraalVM 19.3+ must be present and since it is build on top of OpenJDK 11 this will be the best choice for this tutorial. The easiest way to install (and manage multiple versions of) Java SDKs is with SDKMAN!
Learn how to manage multiple Java SDKs with SDKMAN! with ease
To support native images, make sure to install all needed dependencies. More info can be found in the GraalVM documentation: https://www.graalvm.org/docs/reference-manual/native-image/
GraalVM official documentation: GraalVM
Terminal
The service was developed on macOS with iTerm2 and oh-my-zsh. I also use httpie as my default HTTP client.
IntelliJ
My prefered IDE is IntelliJ and I used this while working on this project.
Learn more about the tools I used on macOS in this article: macOS: essential tools for (Java) developer
Run PostgreSQL with Docker
The application will connect to Postgres server and depending on the profile (dev
, test
, prod
) different configuration will be applied. For this we will need three servers to be running: each with different database name, port and credentials. To simplify the setup, Docker can be utilized.
Dev database
- Create and run the container:
1 | $ docker run --name petclinic-db-dev -p 5433 : 5432 -e POSTGRES_DB=petclinic-dev -e POSTGRES_USER=petclinic-dev -e POSTGRES_PASSWORD=petclinic-dev -d postgres:alpine |
- Run previously stopped container:
1 | $ docker start petclinic-db-dev |
Test database
- Create and run the container:
1 | $ docker run --name petclinic-db-test -p 5434 : 5432 -e POSTGRES_DB=petclinic-test -e POSTGRES_USER=petclinic-test -e POSTGRES_PASSWORD=petclinic-test -d postgres:alpine |
- Run previously stopped container:
1 | $ docker start petclinic-db-test |
Prod database
- Create and run the container:
1 | $ docker run --name petclinic-db -p 5432 : 5432 -e POSTGRES_DB=petclinic -e POSTGRES_USER=petclinic -e POSTGRES_PASSWORD=petclinic -d postgres:alpine |
- Run previously stopped container:
1 | $ docker start petclinic-db |
Getting started
Bootstrap the application
You can bootstrap the application using Maven in command line or you can use the online generator. The online generator allows exploring the extensions and technologies that Quarkus application can be made of and it does not require local Maven installation. You can access the generator here: https://code.quarkus.io
The following extensions are needed to build PetClinic API service:
- RESTEasy JAX-RS – REST framework implementing JAX-RS and more
- RESTEasy Jackson – Jackson serialization support for RESTEasy
- SmallRye OpenAPI – Document your REST APIs with OpenAPI – comes with Swagger UI
- Hibernate ORM with Panache – Define your persistent model in Hibernate ORM with Panache
- Hibernate Validator – Validate data coming to your REST endpoints
- JDBC Driver – PostgreSQL – PostgreSQL database connector
- Flyway – Handle your database schema migrations
Once the dependencies are selected, you can download the zip, extract it and start developing the service.
The downloaded project has a standard Maven project layout. It contains the Maven Wrapper so no local Maven installation is required to develop the project. You will also notice src/main/docker
with Docker files for both native and JVM image.
The main configuration file – application.properties
– is located in src/main/resources
. This folder also holds META-INF/resources
folder for static resources of the application, like index.html
file.
Set Java version to 11 in pom.xml
as well as in Docker files
The online generator generates project with Java 8 by default, so in order to use Java 11 some adjustments are needed.
- In
pom.xml
of the generated project change the Java version:
1 2 | < maven.compiler.source >11</ maven.compiler.source > < maven.compiler.target >11</ maven.compiler.target > |
- In
src/main/docker/Dockerfile.jvm
setARG JAVA_PACKAGE=java-11-openjdk-headless
Run the project in development mode
Once the changes are made you can start the application. Open your terminal, navigate to project’s folder and run the following command:
1 | $ ./mvnw compile quarkus:dev |
Note: Quarkus has three buit-in modes: dev
, test
and prod
depending on how you run the application.
Developing in IntelliJ
In IntelliJ you simply open the project’s folder or the pom.xml
. (File > Open
). The project can be started only with Maven. This can be done with Maven run configurations as there is no main class to start the application like for example in Spring Boot.
For me the best expierience while developing with Quarkus was when I was running the application in the terminal, outside the IntelliJ.
Debugging
When Quarkus application is executed in dev mode it starts with the debug protocol enabled (on port 5005). To debug Quarkus application in IntelliJ you need to attach a debugger to a running proces via Run > Attach to Process
. I had no troubles with debugging the application.
Note: You can run the application in a dev mode with debugging disabled: ./mvnw quarkus:dev -Ddebug=false
, but honestly I did not notice any performance issues with debugger enabled by default.
Live Reload
Live reload is on of the strongest features of Quarkus in my opinion. It works amazing. Basically you can change anything you want in the source code, execute the request and the application re-loads in a blink of an eye. I was refacoring classes and packages, moving files around, adding and removing endpoints and all of this with no single restart.
Data source configuration
All properties go to src/main/resources/application.properties
.
Default data source properties (prod
)
1 2 3 4 | quarkus.datasource.url=jdbc:postgresql: //localhost:5432/petclinic quarkus.datasource.driver=org.postgresql.Driver quarkus.datasource.username=petclinic quarkus.datasource.password=petclinic |
Dev data source properties (dev
)
To set mode (or profile) specific properties use the %mode
:
1 2 3 | %dev.quarkus.datasource.url=jdbc:postgresql: //localhost:5433/petclinic-dev %dev.quarkus.datasource.username=petclinic-dev %dev.quarkus.datasource.password=petclinic-dev |
Test data source properties (test
)
1 2 3 | %test.quarkus.datasource.url=jdbc:postgresql: //localhost:5434/petclinic-test %test.quarkus.datasource.username=petclinic-test %test.quarkus.datasource.password=petclinic-test |
See also: https://quarkus.io/guides/datasource
Flyway migration
To utilize Flyway create db/migration
folder in src/main/resources
and add you migration files. My first migration file is called V1.0.0__PetClinic.sql
and it contains all the schema (DDL) and the sample data for the service.
Note: Quarkus supports SQL import that can be configured via quarkus.hibernate-orm.sql-load-script
for each profile, but I could not make it work. See the issue I reported on Github: https://github.com/quarkusio/quarkus/issues/7358
See also: https://quarkus.io/guides/flyway
JPA Entities
The PetClinic’s domain model is relatively simple, but it consists of some unidirectional and bi-directional associations, as well as basic inheritance which makes it a bit better than simple Hello World kind of model.
Please note that in this example the JPA entities are returned directly in JAX-RS resources by corresponding Panache repositories (see below), therefore entities classes contain a mix of JPA and Jackson annotations.
For example:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | @Entity @Table (name = "visits" ) public class Visit extends BaseEntity { @Column (name = "visit_date" ) @JsonFormat (pattern = "yyyy/MM/dd HH:mm" ) private LocalDateTime date; @NotEmpty @Column (name = "description" ) private String description; @ManyToOne @JoinColumn (name = "pet_id" ) private Pet pet; @ManyToOne @JoinColumn (name = "vet_id" ) private Vet vet; public Visit() { this .date = LocalDateTime.now(); } } @Entity @Table (name = "vets" , uniqueConstraints = @UniqueConstraint (columnNames = { "first_name" , "last_name" }) ) public class Vet extends Person { @ManyToMany (fetch = FetchType.EAGER) @JoinTable (name = "vet_specialties" , joinColumns = @JoinColumn (name = "vet_id" ), inverseJoinColumns = @JoinColumn (name = "specialty_id" )) @JsonIgnore private Set<Specialty> specialties; @OneToMany (cascade = CascadeType.ALL, mappedBy = "vet" , fetch = FetchType.EAGER) @JsonIgnore private Set<Visit> visits; } |
All the entities are located in pl.codeleak.samples.petclinic.model
package.
Hibernate ORM with Panache
If you are familiar with Spring, I guess you have heard of Spring Data project. Hibernate ORM with Panache has similar goal in my opinion: it simplifies JPA development by removing the need of doing repeative and tedious work. Panache supports sorting, pagination, java.util.Optional
and java.utitl.stream.Stream
etc.
You have two approaches to work with Panache: creating entities with PanacheEntity
or creating repositories with PanacheRepository
. I tried both approaches in this project, but due to some issues with inheritance in entities I decided to stick to old-fashioned way.
A basic repository definition with Hibernate ORM with Panache:
1 2 3 4 5 | public class OwnerRepository implements PanacheRepository<Owner> { List<Owner> findByLastName(String lastName) { return list( "lastName" , lastName); } } |
All the repositories are located in pl.codeleak.samples.petclinic.repository
package.
See also: https://quarkus.io/guides/hibernate-orm-panache
Creating REST API
JAX-RS Resources
Quarkus utilizes JAX-RS with RESTEasy. To create API endpoints we need to create JAX-RS resources:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | @Path (OwnerResource.RESOURCE_PATH) @Produces (MediaType.APPLICATION_JSON) public class OwnerResource { public static final String RESOURCE_PATH = "/owners" ; @Context UriInfo uriInfo; @Inject OwnerRepository ownerRepository; @Inject PetRepository petRepository; @GET public Response getAll( @BeanParam PageRequest pageRequest) { } @GET @Path ( "{id}" ) public Response getOne( @PathParam ( "id" ) Long id) { } @GET @Path ( "{id}/pets" ) public List<Pet> getPets( @PathParam ( "id" ) Long id) { } @POST @Consumes (MediaType.APPLICATION_JSON) @Transactional public Response create( @Valid Owner owner) { } } |
Dependency injection is done with CDI – Context and Dependency Injection. The resource objects will be automatically configured by Quarkus. All other dependencies must be configured for dependency injection with CDI annotations.
For example, the repositories can be annotated with @ApplicationScoped
and then injected with @Inject
:
01 02 03 04 05 06 07 08 09 10 11 | @ApplicationScoped public class OwnerRepository implements PanacheRepository<Owner> { List<Owner> findByLastName(String lastName) { return list( "lastName" , lastName); } } @ApplicationScoped public class PetRepository implements PanacheRepository<Pet> { } |
All the resources are located in pl.codeleak.samples.petclinic.api
package.
See also: https://quarkus.io/guides/cdi-reference
Pagination
As mentioned earlier, Panache provides support for paginated results. We can easily utilize this in our resources easily:
1 2 3 4 5 6 | @GET public Response getAll( @BeanParam PageRequest pageRequest) { return Response.ok(((PanacheRepository) petRepository).findAll() .page(Page.of(pageRequest.getPageNum(), pageRequest.getPageSize())) .list()).build(); } |
The PageRequest
is a bean that holds the pageNum
and pageSize
query parameters:
01 02 03 04 05 06 07 08 09 10 11 | public class PageRequest { @QueryParam ( "pageNum" ) @DefaultValue ( "0" ) private int pageNum; @QueryParam ( "pageSize" ) @DefaultValue ( "10" ) private int pageSize; } |
Executing paginated request can be done easily with httpie:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | $ http get : 8080 /owners pageNum== 0 pageSize== 2 HTTP/ 1.1 200 OK Content-Length: 250 Content-Type: application/json [ { "address" : "110 W. Liberty St." , "city" : "Madison" , "firstName" : "George" , "id" : 1 , "lastName" : "Franklin" , "telephone" : "6085551023" }, { "address" : "638 Cardinal Ave." , "city" : "Sun Prairie" , "firstName" : "Betty" , "id" : 2 , "lastName" : "Davis" , "telephone" : "6085551749" } ] |
Transactions
Creating a new object in JPA requires an active transaction. In order to bind the transaction to current method in a resource object use @Transactional
, otherwise an exception will be thrown during the execution of the method:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 | @POST @Consumes (MediaType.APPLICATION_JSON) @Transactional public Response create( @Valid Owner owner) { ownerRepository.persist(owner); var location = uriInfo.getAbsolutePathBuilder() .path( "{id}" ) .resolveTemplate( "id" , owner.getId()) .build(); return Response.created(location).build(); } |
Create new resource with httpie:
01 02 03 04 05 06 07 08 09 10 11 12 | $ http post : 8080 /owners <<< ' { "address" : "110 W. Liberty St." , "city" : "Madison" , "firstName" : "George" , "lastName" : "Franklin" , "telephone" : "6085551023" }' HTTP/ 1.1 201 Created Content-Length: 0 Location: http: //localhost:8080/owners/1042 |
Validation
The project uses Hibernate Validator extension. With this extension you can use standard Hibernate validation annotations (e.g. @NotBlank
) and when the input parameter to the resource methods is annotated with @Valid
the validation will be automatically triggerred and an error response will be returned to the client calling that method.
Example response for the following request:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | $ http post : 8080 /owners <<< '{}' HTTP/ 1.1 400 Bad Request Content-Length: 626 Content-Type: application/json validation-exception: true { "classViolations" : [], "exception" : null , "parameterViolations" : [ { "constraintType" : "PARAMETER" , "message" : "must not be empty" , "path" : "create.owner.address" , "value" : "" }, ... { "constraintType" : "PARAMETER" , "message" : "must not be empty" , "path" : "create.owner.telephone" , "value" : "" } ], "propertyViolations" : [], "returnValueViolations" : [] } |
Note on live reload fumctionality: you can make any change to the source code and execute new request with httpie. The application reloads quickly and you get immediate results. No restarts are needed.
See also: https://quarkus.io/guides/validation
Java 8 Date & Time support
java.util.time
types are supported during JSON serialization and deserialization when the RESTEasy Jackson extension is in the project.
In the below example a visit date with be serialized and deserialized in the format provided by @JsonFormat
annotation:
1 2 3 4 5 6 7 8 9 | @Entity @Table (name = "visits" ) public class Visit extends BaseEntity { @Column (name = "visit_date" ) @JsonFormat (pattern = "yyyy/MM/dd HH:mm" ) private LocalDateTime date; } |
Check how date is serialized using htppie:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | $ http get : 8080 /visits/ 1 HTTP/ 1.1 200 OK Content-Length: 174 Content-Type: application/json { "date" : "2013/01/01 00:00" , "description" : "rabies shot" , "id" : 1 , "pet" : { "birthDate" : "2012/09/04" , "id" : 7 , "name" : "Samantha" }, "vet" : { "firstName" : "Helen" , "id" : 2 , "lastName" : "Leary" } } |
You can also store the visit using the required datetime format in the request body:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | $ http post : 8080 /visits <<< ' { "date" : "2020/01/01 00:00" , "description" : "lorem ipsum" , "pet" : { "id" : 7 }, "vet" : { "id" : 2 } }' HTTP/ 1.1 201 Created Content-Length: 0 Location: http: //localhost:8080/visits/1042 |
OpenAPI / Swagger support
SmallRye OpenAPI extension takes care of providing API documentation and SwaggerUI is enabled in the dev mode.
The default endpoints are:
- OpenAPI documentaion –
/openapi
- SwaggerUI –
/swaggerui
See also: https://quarkus.io/guides/openapi-swaggerui
Integration tests
Quarkus uses JUnit 5 and RESTAssured for integration testing. Tests can be created using @QuarkusTest
annotations and they are executed with test
profile active by default.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | @QuarkusTest public class PetResourceTest { @Test public void pagedList() { given() .when().get( "/pets?pageNum=0&pageSize=2" ) .then() .statusCode( 200 ) .body( "$.size()" , is( 2 ), "name" , containsInAnyOrder( "Leo" , "Basil" ) ); } } |
Quarkus tests require the application to be running. There are possibilities to replace selected beans in test by using CDI @Alternate
beans definitions. The alternate beans must be placed in src/test/java
.
Note: Thanks to the profiles support you can easily configure the datasource for the test
profile with a seperate database container. See Test data source properties.
See also: https://quarkus.io/guides/getting-started-testing
Packaging and running the application
The application can be packaged ./mvnw package
.
It produces the executable quarkus-petclinic-api-1.0.0-runner.jar
file in /target
directory with the dependencies are copied into the target/lib
directory.
1 2 3 4 5 6 7 8 | [INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building thin jar: /Users/rafal.borowiec/Projects/quarkus/quarkus-petclinic-api/target/quarkus-petclinic-api- 1.0 . 0 -runner.jar [INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 1888ms [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 15.868 s [INFO] Finished at: 2020 - 02 -23T19: 18 : 25 + 01 : 00 [INFO] ------------------------------------------------------------------------ |
The application is now runnable using java -jar target/quarkus-petclinic-api-1.0.0-runner.jar
.
1 2 3 | 2020 - 02 - 23 19 : 19 : 10 , 169 INFO [io.quarkus] (main) quarkus-petclinic-api 1.0 . 0 (running on Quarkus 1.2 . 1 .Final) started in 2 .011s. Listening on: http: //0.0.0.0:8080 2020 - 02 - 23 19 : 19 : 10 , 171 INFO [io.quarkus] (main) Profile prod activated. 2020 - 02 - 23 19 : 19 : 10 , 171 INFO [io.quarkus] (main) Installed features: [agroal, cdi, flyway, hibernate-orm, hibernate-orm-panache, hibernate-validator, jdbc-postgresql, narayana-jta, rest-client, resteasy, resteasy-jackson, smallrye-openapi] |
Note: The uber-jar can be packaged with ./mvnw clean package -DskipTests=true -Dquarkus.package.uber-jar=true
Create a Docker container that runs the application in JVM mode
1 2 3 4 5 | $ ./mvnw clean package $ docker build -f src/main/docker/Dockerfile.jvm -t quarkus/petclinic-api-jvm . Successfully built 1a5d963fedfa Successfully tagged quarkus/petclinic-api-jvm:latest |
Run the container with a link do the Postgres database container and override the datasource url with environment variable:
1 2 3 4 5 6 | $ docker run -i --rm -p 8080 : 8080 --link petclinic-db -e QUARKUS_DATASOURCE_URL= 'jdbc:postgresql://petclinic-db/petclinic' quarkus/petclinic-api-jvm 2020 - 02 - 23 20 : 39 : 18 , 949 INFO [io.quarkus] (main) quarkus-petclinic-api 1.0 . 0 (running on Quarkus 1.2 . 1 .Final) started in 3 .475s. Listening on: http: //0.0.0.0:8080 2020 - 02 - 23 20 : 39 : 18 , 949 INFO [io.quarkus] (main) Profile prod activated. 2020 - 02 - 23 20 : 39 : 18 , 949 INFO [io.quarkus] (main) Installed features: [agroal, cdi, flyway, hibernate-orm, hibernate-orm-panache, hibernate-validator, jdbc-postgresql, narayana-jta, rest-client, resteasy, resteasy-jackson, smallrye-openapi |
Note: petclinic-db
is a name of the Postgres container created here: Prod database. We also need to pass the datasource url. Read more about overriding the configuration properties at runtime: Overriding properties at runtime
Create native executable
You can create a native executable using the following command:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | $ ./mvnw package -Pnative [INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Building native image from /Users/rafal.borowiec/Projects/quarkus/quarkus-petclinic-api/target/quarkus-petclinic-api- 1.0 . 0 - native -image-source-jar/quarkus-petclinic-api- 1.0 . 0 -runner.jar ... [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] (typeflow): 72 , 535.72 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] (objects): 49 , 325.68 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] (features): 3 , 115.04 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] analysis: 135 , 220.10 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] (clinit): 1 , 966.77 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] universe: 6 , 919.51 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] (parse): 13 , 679.33 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] (inline): 18 , 193.40 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] (compile): 70 , 849.75 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] compile: 111 , 062.75 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] image: 8 , 843.46 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] write: 1 , 789.58 ms [quarkus-petclinic-api- 1.0 . 0 -runner: 50503 ] [total]: 282 , 727.03 ms [INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 287304ms [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 04 : 58 min [INFO] Finished at: 2020 - 02 -23T19: 25 : 10 + 01 : 00 [INFO] ------------------------------------------------------------------------ |
The process of creating the native executable takes quite some time but it is worth waiting for it to finish to see the startup time of application:
1 2 3 4 5 6 | $ ./target/quarkus-petclinic-api- 1.0 . 0 -runner 2020 - 02 - 23 19 : 26 : 03 , 959 INFO [io.quarkus] (main) quarkus-petclinic-api 1.0 . 0 (running on Quarkus 1.2 . 1 .Final) started in 0 .066s. Listening on: http: //0.0.0.0:8080 2020 - 02 - 23 19 : 26 : 03 , 959 INFO [io.quarkus] (main) Profile prod activated. 2020 - 02 - 23 19 : 26 : 03 , 959 INFO [io.quarkus] (main) Installed features: [agroal, cdi, flyway, hibernate-orm, hibernate-orm-panache, hibernate-validator, jdbc-postgresql, narayana-jta, rest-client, resteasy, resteasy-jackson, smallrye-openapi] |
0.67 seconds for native executable to start comparing to 2 seconds for the JVM version.
Create a Docker container that runs the application in native mode
By default, the native executable is created in the format supported by your operating system. Because the container may not use the same executable format as the one produced by your operating system, Maven build can produce an executable from inside a container:
1 | $ ./mvnw package -Pnative -Dquarkus. native .container-build= true |
To adjust the version of the builder image you need to set quarkus.native.builder-image
property:
1 | $ ./mvnw clean package -Pnative -DskipTests= true -Dquarkus. native .container-build= true -Dquarkus. native .builder-image=quay.io/quarkus/ubi-quarkus- native -image: 20.0 . 0 -java11 |
And now, build and run the container:
1 2 3 | $ docker build -f src/main/docker/Dockerfile. native -t quarkus/petclinic-api . $ docker run -i --rm -p 8080 : 8080 quarkus/petclinic-api |
Note: More on building native executables can be found in the Quarkus documentation: https://quarkus.io/guides/building-native-image
Source code
The source code for this article can be found on Github: https://github.com/kolorobot/quarkus-petclinic-api
Published on Java Code Geeks with permission by Rafal Borowiec, partner at our JCG program. See the original article here: Getting started with Quarkus Opinions expressed by Java Code Geeks contributors are their own. |