Building and Running Quarkus(Supersonic Subatomic Java) application native image in docker container using PODMAN
This article is targeted towards developers, architects and managers that look for additional information on Podman and how to setup podman in Ubuntu and high level uses of Podman. Article also demonstrate how to create a docker image using quarkus native and run the container and emphasize on the amazing fast(supersonic) boot time of the Quarkus application.
Quick Intro for Podman and Quarkus
Quarkus is a Kubernetes Native Java framework tailored for GraalVM and HotSpot, crafted from best-of-breed Java libraries and standards. The goal of Quarkus is to make Java a leading platform in Kubernetes and serverless environments while offering developers a unified reactive and imperative programming model to optimally address a wider range of distributed application architectures. Quarkus provides Amazingly fast boot time, incredibly low RSS memory (not just heap size!) offering near instant scale up and high-density memory utilization in container orchestration platforms like Kubernetes. Quarkus provides live reloading f the code and developers don’t need to restart servers once they change the code .
Podman offer experience similar to docker command line however it don’t need to have daemon processes like docker daemon. Podman and docker images are compatible. Also, podman can run as non-root user however docker always needs root as user. In summary Podman similar with Docker CLI however it has more benefits over Docker CLIs
What we will be doing here
In the below exercise we will see using podman how to build a native docker image from a quarkus application and then run the docker image.
A simple rest application built using quarkus can be started in approx .1 sec in native mode and please refer below picture for details . In this exercise we will highlight on the amazing fast(supersonic) boot time of the quarkus application.
Lets start hands on
Step 1: Install podman in Ubuntu 20.04.1 LTS. Execute the below commands
echo “deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_20.04/ /” | sudo tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_20.04/Release.key | sudo apt-key add -
sudo apt-get update
sudo apt-get -y upgrade
sudo apt-get -y install podman
Step 2: Clone a Quarkus Repository in Local
$ git clone https://github.com/dhrsana1/quarkus_rest_app.git
Step 3: Use podman to build the project using dockerfile
Cd to the directory where the repository is cloned
Run the below podman command to build the docker images
podman build -t quarkusdemo .
Results of the command — here the images was build already earlier.
STEP 1: FROM quay.io/quarkus/centos-quarkus-maven:20.2.0-java11 AS build
STEP 2: COPY pom.xml /usr/src/app/
→ Using cache 8d180abf5f5403a76a439d06ef3a04b4fa78cf7482864ff10266d64ca2e41c35
STEP 3: RUN mvn -f /usr/src/app/pom.xml -B de.qaware.maven:go-offline-maven-plugin:1.2.5:resolve-dependencies
→ Using cache 4f4bf51381148d4b0ce04c8f85c918238c43c3706d820f640381b190f5b27740
STEP 4: COPY src /usr/src/app/src
→ Using cache 0ee311002a8dd6f74d74337a8f9041afaedb857193f5d03066c9b58236ba260c
STEP 5: USER root
→ Using cache dae89d8530dc6f569ca86782d4640263010322cdcf99d9f29691f45c91425302
STEP 6: RUN chown -R quarkus /usr/src/app
→ Using cache 0fe14ee87695092a793a16706b8893525301eba156b7cc9416ee9ccb3f004a1b
STEP 7: USER quarkus
→ Using cache 7b63bb9aefce30c11d9c83eb3d733e9fb015a73dfeeda462c8477ce52b30a1d7
STEP 8: RUN mvn -f /usr/src/app/pom.xml -Pnative clean package
→ Using cache 3bc5a7c86c772c636b6cb055ff17e7f8c8ed38bda249774e0b53a4a7cd4af53a
STEP 9: FROM registry.access.redhat.com/ubi8/ubi-minimal
STEP 10: WORKDIR /work/
→ Using cache 70d8aa7009c8d398df22f4f9e2c67fe6ff259d994fb520d142eda5e7827f9a3b
STEP 11: COPY — from=build /usr/src/app/target/*-runner /work/application
→ Using cache 71480365d6c544d4be31379bb19056ae19ed5303032bbba665232d4359681e25
STEP 12: RUN chmod 775 /work /work/application && chown -R 1001 /work && chmod -R “g+rwX” /work && chown -R 1001:root /work
→ Using cache c83e23c2eec36b96a11234ac3cb113500cc79a3679a14136bac9b495d1afc6aa
STEP 13: EXPOSE 8080
→ Using cache b20e2a8b1e2f341f319841ce4a7ca0f8f1aedc6b410ed773449801084bd2ecae
STEP 14: USER 1001
→ Using cache f348c2835e9fdd427144fa73e4ad52a25c57a7c6cf42723f2f7c7126ad47cb43
STEP 15: CMD [“./application”, “-Dquarkus.http.host=0.0.0.0”]
→ Using cache e6aed77523d6453d11aaa6d45f417b72fd2c7ed6eedf17edeff6f878fbda3dd9
STEP 16: COMMIT quarkusdemo
Step 4: List all podman images
Step 5: Running images using podman
podman run -p 8080:8080 quarkusdemo
Step 6: Curl the rest end point of native quarkus application
You can see the response coming from the quarkus application — rest end point
Step7: You will notice that the native image started in approximately .1 second
As you see in the above example podman command lets you run containers as standalone entities, without requiring that Kubernetes, the Docker runtime, or any other container runtime be involved. It is a tool that can act as a replacement for the docker command, implementing the same command-line syntax, while it adds even more container management features. Quarkus uses Ahead of Time compilation strategy while building the application, which gives the benefit to loading only the necessary classes which helps to start the application. Here in this example we can see Quarkus apps can be compiled down to a native executable, for even greater efficiency using GrallVM and the native build . Using Mandrel (a downstream distribution of GraalVM), the quarkus application is analyzed to find “dead code” (code paths which will never be visited at runtime) and eliminate this from the application executable. This results in tiny and lightweight runnable applications that start up in tens of milliseconds, and require tens of megabytes of memory at runtime.