Last updated: Mon Sep 12 09:58:24 CEST 2022
Author: Lukasz Ochmanski (github@ochmanski.de)
This project uses Quarkus, the Supersonic Subatomic Java Framework.
If you want to learn more about Quarkus, please visit its website: https://quarkus.io/ .
- 1. How to clone:
- 2. Running the application in dev mode
- 3. Packaging and running the application
- 4. Creating a native executable
- 5. how to create a docker image locally:
- 6. How to start with Docker
- 7. Docker examples
- 9. How to bump a version?
- 10. Related Guides
- 11. Including resources
git clone git@github.com:lukaszochmanski/quarkus-jpa-example.git \
~/Workspace/de/ochmanski/microservices/quarkus/quarkus-jpa-example
You can run your application in dev mode that enables live coding using:
gradle quarkusDev
alternatively, you may call:
quarkus dev
The second call will work, if you have Quarkus SDK installed:
sdk install quarkus
to test:
curl -w "\n" http://localhost:8080/hello
curl http://localhost:8080/q/health/live
curl http://localhost:8080/q/health/ready
NOTE: Quarkus now ships with a Dev UI, which is available in dev mode only at http://localhost:8080/q/dev/.
The application can be packaged using:
gradle build
It produces the quarkus-run.jar
file in the build/quarkus-app/
directory.
Be aware that it’s not an über-jar as the dependencies are copied into the build/quarkus-app/lib/
directory.
The application is now runnable using java -jar build/quarkus-app/quarkus-run.jar
.
If you want to build an über-jar, execute the following command:
gradle build -Dquarkus.package.type=uber-jar
The application, packaged as an über-jar, is now runnable using java -jar build/*-runner.jar
.
You can create a native executable using:
gradle build -Dquarkus.package.type=native
Or, if you don't have GraalVM installed, you can run the native executable build in a container using:
gradle build -Dquarkus.package.type=native -Dquarkus.native.container-build=true
You can then execute your native executable with: ./build/code-with-quarkus-1.0.18-SNAPSHOT-runner
If you want to learn more about building native executables, please consult https://quarkus.io/guides/gradle-tooling.
In this case the default image quay.io/quarkus/ubi-quarkus-native-image:22.0-java11
will be used.
This can be changed in build.gradle
file:
quarkusBuild {
nativeArgs {
containerBuild = true
builderImage = "quay.io/quarkus/ubi-quarkus-native-image:22.0.0-java11"
containerRuntime = "docker"
}
}
or:
quarkusBuild {
nativeArgs {
containerBuild = true
builderImage = "base/images/red-hat/red-hat-8-5/quay-io/quarkus/quarkus-micro-image:1.0.0"
containerRuntime = "docker"
}
}
command to execute:
GRAALVM_HOME='$HOME/.sdkman/candidates/java/22.1.0.r17-grl'
groupId='de/ochmanski/microservices'
artifactId='quarkus-jpa-example'
DOCKER_REPOSITORY="snapshots"
gradle build \
-Dquarkus.package.type=native \
-Dquarkus.native.container-build=true \
-Dquarkus.native.container-runtime=docker \
-Dquarkus.native.java-home=${GRAALVM_HOME} \
-Dquarkus.native.native-image-xmx=7G \
-Dquarkus.jib.always-cache-base-image=true \
-Dquarkus.container-image.builder=jib \
-Dquarkus.container-image.build=true \
-Dquarkus.container-image.push=false \
-Dquarkus.container-image.name=${artifactId} \
-Dquarkus.container-image.group=${DOCKER_REPOSITORY}/${groupId} \
-Dquarkus.container-image.registry=${HOST}
It is a recommended way of building the project.
Main advantage of this method is that it doesn't require docker
installation, and it works fully offline. However, it requires more maintenance, expertise and
initial effort, to configure the environment. But you need to do it only once.
This method is faster because it has less virtualization layers, than the container build method
described in section
5.1.
It is running directly in your OS, without the Docker service. Therefore, it also consumes less memory, and less CPU.
As everything that is not virtualized, comes with a price.
This solution is not as portable, as the solution presented above
in 5.1..
As of writing this document, it only works on Linux platform. If you use Windows, or MacOS, you may face problems.
This option requires you to install native-image
first:
sdk install java java=22.1.0.r17-grl
GRAALVM_HOME=$HOME/.sdkman/candidates/java/22.1.0.r17-grl
$GRAALVM_HOME/bin/gu install native-image
sdk install quarkus
and execute the build:
quarkus build --native
a similar command for gradle users:
groupId='de/ochmanski/microservices'
artifactId='quarkus-jpa-example'
DOCKER_REPOSITORY="snapshots"
gradle build \
-Dquarkus.package.type=native \
-Dquarkus.native.container-build=false \
-Dquarkus.native.container-runtime=docker \
-Dquarkus.native.java-home=${GRAALVM_HOME} \
-Dquarkus.native.native-image-xmx=7G \
-Dquarkus.jib.always-cache-base-image=true \
-Dquarkus.container-image.builder=jib \
-Dquarkus.container-image.build=true \
-Dquarkus.container-image.push=false \
-Dquarkus.container-image.name=${artifactId} \
-Dquarkus.container-image.group=${DOCKER_REPOSITORY}/${groupId} \
-Dquarkus.container-image.registry=${HOST}
Note that running the command in MacOS or in Windows will result in the following error:
> Task :quarkusBuild FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':quarkusBuild'.
> io.quarkus.builder.BuildException: Build failure: Build failed due to errors
[error]: Build step io.quarkus.container.image.jib.deployment.JibProcessor#buildFromNative threw an exception: java.lang.RuntimeException:
The native binary produced by the build is not a Linux binary and therefore cannot be used in a Linux container image.
Consider adding "quarkus.native.container-build=true" to your configuration
The reason why it doesn't work, is that it can only run inside a true Linux, or inside another docker image.
If you try to build it inside a docker container, you will not see this error. This is exactly the case in our CI
environment.
We run our build pipelines inside another Docker container. You may find details in buildspec.yml
file.
-Dquarkus.native.container-build=false
This option is good for someone that is not a java developer and wants runtime environment quickly.
docker run --rm -p 8080:8080 --name="quarkus-jpa-example-1.0.18" \
-it ../releases/de/ochmanski/microservices/quarkus-jpa-example:1.0.18
However, this will probably not work, because the database url is not the same inside a docker container.
One solution is to open the container and install mysql database there.
Another solution is to use the database that already exists on your machine.
A third solution would be to connect to our dev database instance.
Instruction steps are given in point 7.
Below, I present a few examples, how running the app can be achieved without installing java.
Remember, that the running MySQL database, with a working schema is needed first.
In given examples I used: 127.0.0.1:3306/quarkus_jpa_example_v1
It could be anything you wish, but remember that the address
, port
and schema
must exist and they must match your configuration.
Set it up, before you start the Docker container. Otherwise, you will see an error.
cd ~/Workspace/de/ochmanski/microservices/quarkus-jpa-example
docker run --rm -p 8080:8080 --name="quarkus-jpa-example-1.0.18" \
--mount type=bind,source=$PWD/src/main/resources/application-docker.yml,\
target=/work/config/application.yml \
-it releases/de/ochmanski/microservices/quarkus-jpa-example:1.0.18
info:
application:
mounted: yes
quarkus:
datasource:
jdbc:
url: mysql://host.docker.internal:3306/quarkus_jpa_example_v1?serverTimezone=UTC&useLegacyDatetimeCode=false'
password: <changeme>
http:
cors: true
port: 8080
swagger-ui:
always-include: true
path: '/swagger-ui.html'
log:
level: DEBUG
Sometimes, you may want to re-use your local QUARKUS_DATASOURCE_PASSWORD
. If the value of the variable is already set,
you may pass the value directly into the docker container using -e
flag. In such case, you can remove the password
from application-docker.yml
file.
cd ~/Workspace/de/ochmanski/microservices/quarkus-jpa-example
docker run -it --rm -p 8080:8080 --name="quarkus-jpa-example-1.0.18" \
--mount type=bind,source=$PWD/src/main/resources/application-docker.yml,\
target=/work/config/application.yml \
-e QUARKUS_DATASOURCE_PASSWORD=$QUARKUS_DATASOURCE_PASSWORD \
releases/de/ochmanski/microservices/quarkus-jpa-example:1.0.18
info:
application:
mounted: yes
quarkus:
datasource:
jdbc:
url: mysql://host.docker.internal:3306/quarkus_jpa_example_v1?serverTimezone=UTC&useLegacyDatetimeCode=false
http:
cors: true
port: 8080
swagger-ui:
always-include: true
path: '/swagger-ui.html'
log:
level: DEBUG
docker run --rm -p 8080:8080 --name="quarkus-jpa-example-1.0.18" \
-e QUARKUS_DATASOURCE_PASSWORD=$QUARKUS_DATASOURCE_PASSWORD \
-it releases/de/ochmanski/microservices/quarkus-jpa-example:1.0.18
NOTE:
quarkus.datasource.url
must contain:jdbc:mysql://host.docker.internal:3306
notjdbc:mysql://localhost:3306
!
because docker container doesn't connect to your localhost network, the waygradle quarkusDev
does.
In a docker containerlocalhost
is not resolved to127.0.0.1
of your physical machine.
This is not recommended, but in case you are a DevOp, and you want to open the docker image, and debug it, before publishing a final RELEASE, you may create a SNAPSHOT of the image locally, with the following command:
gradle jibDockerBuild
Please note, that the same snapshot will be automatically created by CodeBuild pipeline, so there is no need to create it locally, you may simply push the commit into the remote git repository and create the image direcly in the CodeBuild pipeline. The result will be the same.
look at the output of the gradle command in the console. Assuming that the created docker image is identified as:
1.0.18-SNAPSHOT
, you may run it in the following manner:
cd ~/Workspace/de/ochmanski/microservices/quarkus-jpa-example
docker run --rm -p 8080:8080 --name="quarkus-jpa-example-1.0.18-SNAPSHOT" \
--mount type=bind,source=$PWD/src/main/resources/application-docker.yml,\
target=/work/config/application.yml \
-it snapshots/de/ochmanski/microservices/quarkus-jpa-example:1.0.18-SNAPSHOT
NOTE:
quarkus.datasource.url
must contain:jdbc:mysql://host.docker.internal:3306
notjdbc:mysql://localhost:3306
!
because docker container doesn't connect to your localhost network, the waygradle quarkusDev
does.
In a docker containerlocalhost
is not resolved to127.0.0.1
of your physical machine.
look at the output of the gradle command in the console. Assuming that the created docker image is identified as:
1.0.18-SNAPSHOT
, you may open it in the following manner:
cd ~/Workspace/de/ochmanski/microservices/quarkus-jpa-example
docker run --rm -ti --privileged --entrypoint /bin/sh --rm -p 8080:8080 --name="quarkus-jpa-example-1.0.18-SNAPSHOT" \
--mount type=bind,source=$PWD/src/main/resources/application-docker.yml,\
target=/work/config/application.yml \
-it snapshots/de/ochmanski/microservices/quarkus-jpa-example:1.0.18-SNAPSHOT
info:
application:
mounted: yes
quarkus:
datasource:
jdbc:
url:mysql://host.docker.internal:3306/quarkus_jpa_example_v1?serverTimezone=UTC&useLegacyDatetimeCode=false
password: <changeme>
http:
cors: true
port: 8080
swagger-ui:
always-include: true
path: '/swagger-ui.html'
log:
level: DEBUG
git bump
or, standard way:
git checkout main
git tag -a 1.0.0 -m 'please always add -a flag, which is short for "annotated"'
git push --follow-tags
Hibernate Validator (guide): Validate object properties (field, getter) and
method parameters for your beans (REST, CDI, JPA)
Supporting native in your application GraalVM imposes a number of constraints and making your application a native executable might require a few tweaks.
https://quarkus.io/guides/writing-native-applications-tips#including-resources
https://quarkus.io/guides/writing-native-applications-tips#including-resources-2
quarkus.native.resources.includes=foo/**,bar/**/*.txt
Copyright 2023 Lukasz Ochmanski
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.