Quarkus – Supersonic Subatomic Java, trying out some Quarkus code guides (part2)

Marc Lameriks

In this article, you can read more about a Quarkus code guide I tried out, related to the following topic:

  • Packaging the native executable in a container

In a next article, you can read more about another Quarkus code guide I tried out, related to the following topic:

  • The ability to automatically generate Kubernetes resources by Quarkus

Quarkus guide “Building a Native Executable”

From the Quarkus guide “Creating Your First Application, part “What’s next?”, I clicked on the link “building a native executable guide”.
[https://quarkus.io/guides/getting-started#whats-next]

Building a native executable requires using a distribution of GraalVM.

In my previous article I already covered some of the topics in this code guide. So, I will now continue with the topic related to “Creating a container”.
[https://quarkus.io/guides/building-native-image#creating-a-container]

Remember, for compiling the application to a native executable, I described the following two ways:

  • By using a local GraalVM installation
  • By leveraging a container runtime such as Docker and using a Docker container that embeds GraalVM

[https://technology.amis.nl/2020/09/01/quarkus-supersonic-subatomic-java-trying-out-some-quarkus-code-guides-part1/]

This guide continues with the code in the existing “getting-started” Maven project.

Creating a container manually

You can run the application in a container using the JAR produced by the Quarkus Maven Plugin or by using the produced native executable.

Quarkus provides Dockerfile’s for both options. In this article I will explore these options further.

Remark:
The difference between the Dockerfile.fast-jar and Dockerfile.jvm (both used to build a container that runs the Quarkus application in JVM mode) is the use of four distinct layers in the fast variant:

# We make four distinct layers so if there are application changes the library layers can be re-used
COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/
COPY --chown=1001 target/quarkus-app/*.jar /deployments/
COPY --chown=1001 target/quarkus-app/app/ /deployments/app/
COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/

If you need more information about Docker, you can have a look at the “Dockerfile reference” and the “Docker Cheat Sheet”.
[https://www.docker.com/]

The provided Dockerfiles use UBI (Universal Base Image) as parent image. This base image has been tailored to work perfectly in containers. The Dockerfiles use the minimal version of the base image to reduce the size of the produced image.
[https://quarkus.io/guides/building-native-image#manually]

For more information please see: https://www.redhat.com/en/blog/introducing-red-hat-universal-base-image

Build a container that runs the Quarkus application in JVM mode

Below, you can see the content of the src/main/docker/Dockerfile.jvm Dockerfile, provided by the Quarkus project generation:

####
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
#
# Before building the docker image run:
#
# mvn package
#
# Then, build the image with:
#
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/getting-started-jvm .
#
# Then run the container using:
#
# docker run -i --rm -p 8080:8080 quarkus/getting-started-jvm
#
# If you want to include the debug port into your docker image
# you will have to expose the debug port (default 5005) like this :  EXPOSE 8080 5050
# 
# Then run the container using : 
#
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/getting-started-jvm
#
###
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1

ARG JAVA_PACKAGE=java-11-openjdk-headless
ARG RUN_JAVA_VERSION=1.3.8

ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'

# Install java and the run-java script
# Also set up permissions for user `1001`
RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \
    && microdnf update \
    && microdnf clean all \
    && mkdir /deployments \
    && chown 1001 /deployments \
    && chmod "g+rwX" /deployments \
    && chown 1001:root /deployments \
    && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
    && chown 1001 /deployments/run-java.sh \
    && chmod 540 /deployments/run-java.sh \
    && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security

# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"

COPY target/lib/* /deployments/lib/
COPY target/*-runner.jar /deployments/app.jar

EXPOSE 8080
USER 1001

ENTRYPOINT [ "/deployments/run-java.sh" ]

As you can see, this Dockerfile uses the following application resources:

Next, I followed the instructions in the Dockerfile.

I used vagrant ssh to connect into the running VM. Next, in order to build the image, I used the following command on the Linux Command Prompt:

cd /vagrant/applications/getting-started
mvn package
docker build -f src/main/docker/Dockerfile.jvm -t quarkus/getting-started-jvm .

With the following output (only showing the part about the image build):


Sending build context to Docker daemon  49.57MB
Step 1/11 : FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
8.1: Pulling from ubi8/ubi-minimal
b26afdf22be4: Pull complete
218f593046ab: Pull complete
Digest: sha256:df6f9e5d689e4a0b295ff12abc6e2ae2932a1f3e479ae1124ab76cf40c3a8cdd
Status: Downloaded newer image for registry.access.redhat.com/ubi8/ubi-minimal:8.1
 —> 91d23a64fdf2
Step 2/11 : ARG JAVA_PACKAGE=java-11-openjdk-headless
 —> Running in 24697477d296
Removing intermediate container 24697477d296
 —> 3818465cc8fa
Step 3/11 : ARG RUN_JAVA_VERSION=1.3.8
 —> Running in e1f40a97995f
Removing intermediate container e1f40a97995f
 —> c45c7ada9216
Step 4/11 : ENV LANG=’en_US.UTF-8′ LANGUAGE=’en_US:en’
 —> Running in 40779cf018dd
Removing intermediate container 40779cf018dd
 —> eea2c4e04c6c
Step 5/11 : RUN microdnf install curl ca-certificates ${JAVA_PACKAGE}     && microdnf update     && microdnf clean all     && mkdir /deployments     && chown 1001 /deployments     && chmod “g+rwX” /deployments     && chown 1001:root /deployments     && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh     && chown 1001 /deployments/run-java.sh     && chmod 540 /deployments/run-java.sh     && echo “securerandom.source=file:/dev/urandom” >> /etc/alternatives/jre/lib/security/java.security
 —> Running in adfa712e3908

(process:6): librhsm-WARNING **: 09:38:48.162: Found 0 entitlement certificates

(process:6): librhsm-WARNING **: 09:38:48.170: Found 0 entitlement certificates

(process:6): libdnf-WARNING **: 09:38:48.176: Loading “/etc/dnf/dnf.conf”: IniParser: Can’t open file
Downloading metadata…
Downloading metadata…
Downloading metadata…
Package                                                          Repository          Size
Installing:
 alsa-lib-1.2.1.2-3.el8.x86_64                                   ubi-8-appstream 451.2 kB
 avahi-libs-0.7-19.el8.x86_64                                    ubi-8-baseos     64.6 kB
 copy-jdk-configs-3.7-1.el8.noarch                               ubi-8-appstream  27.3 kB
 cups-libs-1:2.2.6-33.el8.x86_64                                 ubi-8-baseos    442.0 kB
 dbus-libs-1:1.12.8-10.el8_2.x86_64                              ubi-8-baseos    187.6 kB
 freetype-2.9.1-4.el8.x86_64                                     ubi-8-baseos    402.7 kB
 java-11-openjdk-headless-1:11.0.8.10-0.el8_2.x86_64             ubi-8-appstream  41.6 MB
 javapackages-filesystem-5.3.0-1.module+el8+2447+6f56d9a6.noarch ubi-8-appstream  31.1 kB
 lcms2-2.9-2.el8.x86_64                                          ubi-8-appstream 168.6 kB
 libjpeg-turbo-1.5.3-10.el8.x86_64                               ubi-8-appstream 159.2 kB
 libpng-2:1.6.34-5.el8.x86_64                                    ubi-8-baseos    129.0 kB
 lksctp-tools-1.0.18-3.el8.x86_64                                ubi-8-baseos    101.9 kB
 lua-5.3.4-11.el8.x86_64                                         ubi-8-appstream 197.4 kB
 tzdata-java-2020a-1.el8.noarch                                  ubi-8-appstream 193.4 kB
Transaction Summary:
 Installing:       14 packages
 Reinstalling:      0 packages
 Upgrading:         0 packages
 Removing:          0 packages
 Downgrading:       0 packages
Downloading packages…
Running transaction test…
Installing: tzdata-java;2020a-1.el8;noarch;ubi-8-appstream
Installing: alsa-lib;1.2.1.2-3.el8;x86_64;ubi-8-appstream
Installing: lcms2;2.9-2.el8;x86_64;ubi-8-appstream
Installing: lua;5.3.4-11.el8;x86_64;ubi-8-appstream
Installing: copy-jdk-configs;3.7-1.el8;noarch;ubi-8-appstream
Installing: libjpeg-turbo;1.5.3-10.el8;x86_64;ubi-8-appstream
Installing: javapackages-filesystem;5.3.0-1.module+el8+2447+6f56d9a6;noarch;ubi-8-appstream
Installing: lksctp-tools;1.0.18-3.el8;x86_64;ubi-8-baseos
Installing: (null)
Installing: libpng;2:1.6.34-5.el8;x86_64;ubi-8-baseos
Installing: (null)
Installing: freetype;2.9.1-4.el8;x86_64;ubi-8-baseos
Installing: (null)
Installing: dbus-libs;1:1.12.8-10.el8_2;x86_64;ubi-8-baseos
Installing: (null)
Installing: avahi-libs;0.7-19.el8;x86_64;ubi-8-baseos
Installing: (null)
Installing: cups-libs;1:2.2.6-33.el8;x86_64;ubi-8-baseos
Installing: (null)
Installing: java-11-openjdk-headless;1:11.0.8.10-0.el8_2;x86_64;ubi-8-appstream
Installing: (null)
Installing: (null)
Complete.

(process:88): librhsm-WARNING **: 09:39:48.421: Found 0 entitlement certificates

(process:88): librhsm-WARNING **: 09:39:48.436: Found 0 entitlement certificates

(process:88): libdnf-WARNING **: 09:39:48.439: Loading “/etc/dnf/dnf.conf”: IniParser: Can’t open file
Downloading metadata…
Downloading metadata…
Downloading metadata…
Package                                            Repository          Size
Installing:
 acl-2.2.53-1.el8.x86_64                           ubi-8-baseos     83.0 kB
 cracklib-2.9.6-15.el8.x86_64                      ubi-8-baseos     95.5 kB
 cracklib-dicts-2.9.6-15.el8.x86_64                ubi-8-baseos      4.1 MB
 cryptsetup-libs-2.2.2-1.el8.x86_64                ubi-8-baseos    438.7 kB

Cleanup: tzdata;2019c-1.el8;noarch;installed
Updating: (null)
Cleanup: libgcc;8.3.1-4.5.el8;x86_64;installed
Updating: (null)
Updating: (null)
Complete.

(microdnf:428): librhsm-WARNING **: 09:41:07.115: Found 0 entitlement certificates

(microdnf:428): librhsm-WARNING **: 09:41:07.121: Found 0 entitlement certificates

(microdnf:428): libdnf-WARNING **: 09:41:07.124: Loading “/etc/dnf/dnf.conf”: IniParser: Can’t open file
Complete.
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 20218  100 20218    0     0  44047      0 –:–:– –:–:– –:–:– 43952
Removing intermediate container adfa712e3908
 —> eedc98908837
Step 6/11 : ENV JAVA_OPTIONS=”-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager”
 —> Running in b6ca56407d27
Removing intermediate container b6ca56407d27
 —> ef0d7a761730
Step 7/11 : COPY target/lib/* /deployments/lib/
 —> 05b7920f320e
Step 8/11 : COPY target/*-runner.jar /deployments/app.jar
 —> 91c87499f38b
Step 9/11 : EXPOSE 8080
 —> Running in 59a65a8d0320
Removing intermediate container 59a65a8d0320
 —> ff0941ccfcbd
Step 10/11 : USER 1001
 —> Running in f0a9e7464e88
Removing intermediate container f0a9e7464e88
 —> 5a06df536e73
Step 11/11 : ENTRYPOINT [ “/deployments/run-java.sh” ]
 —> Running in 799381d98a8b
Removing intermediate container 799381d98a8b
 —> b41bf47f82ac
Successfully built b41bf47f82ac
Successfully tagged quarkus/getting-started-jvm:latest
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

In order to get a list of all the docker images, I used the following command on the Linux Command Prompt:

docker image ls

With the following output:

Here you can see that image quarkus/getting-started-jvm:latest is created.

Remark:
See the Dockerfile and the option -t used in the docker build command (docker build -f src/main/docker/Dockerfile.jvm -t quarkus/getting-started-jvm .).
–tag , -t: Name and optionally a tag in the ‘name:tag’ format
[https://docs.docker.com/engine/reference/commandline/build/]

Next, in order to run the container, I used the following command on the Linux Command Prompt:

docker run -i --rm -p 8090:8090 quarkus/getting-started-jvm

Remark:
In my previous article I described how I changed the application HTTP port from 8080 to 8090, via src/main/resources/application.properties.
[https://technology.amis.nl/2020/09/01/quarkus-supersonic-subatomic-java-trying-out-some-quarkus-code-guides-part1/]

So, I needed to expose port 8090 externally (instead of 8080), mapped to port 8090 inside the container.
See the Dockerfile and the option -p used in the docker run command (docker run -i –rm -p 8080:8080 quarkus/ quarkus/getting-started-jvm .).
–publish , -p: Publish a container’s port(s) to the host
[https://docs.docker.com/engine/reference/commandline/run/]

With the following output:


exec java -Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager -XX:+ExitOnOutOfMemoryError -cp . -jar /deployments/app.jar




Powered by Quarkus 1.7.0.Final
2020-08-30 10:22:11,001 INFO  [io.quarkus] (main) getting-started 1.0-SNAPSHOT on JVM (powered by Quarkus 1.7.0.Final) started in 6.542s. Listening on: http://0.0.0.0:8090
2020-08-30 10:22:11,382 INFO  [io.quarkus] (main) Profile prod activated.
2020-08-30 10:22:11,384 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]

Then, in the Web Browser on my Windows laptop, I entered the URL: http://localhost:8090/hello

And I got the following result:

So, running the application in a container using the JAR produced by the Quarkus Maven Plugin worked.

Remark:
Remember that on my Windows laptop, I could call port 8090 of my guest operating system because via port forwarding this was made possible.
[https://technology.amis.nl/2020/08/17/quarkus-supersonic-subatomic-java-setting-up-a-demo-environment-using-vagrant-and-oracle-virtualbox/]

Build a container that runs the Quarkus application in native (no JVM) mode

When using a local GraalVM installation, the native executable targets your local operating system (Linux, macOS, Windows etc). However, as a container may not use the same executable format as the one produced by your operating system, you can instruct the Maven build to produce an executable by leveraging a container runtime (as I described in my previous article).
[https://technology.amis.nl/2020/09/01/quarkus-supersonic-subatomic-java-trying-out-some-quarkus-code-guides-part1/]

The produced executable will be a 64 bit Linux executable, so depending on your operating system it may no longer be runnable. However, it’s not an issue as we are going to copy it to a container.
[https://quarkus.io/guides/building-native-image#manually]

Below, you can see the content of the src/main/docker/Dockerfile.native Dockerfile, provided by the Quarkus project generation:

####
# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode
#
# Before building the docker image run:
#
# mvn package -Pnative -Dquarkus.native.container-build=true
#
# Then, build the image with:
#
# docker build -f src/main/docker/Dockerfile.native -t quarkus/getting-started .
#
# Then run the container using:
#
# docker run -i --rm -p 8080:8080 quarkus/getting-started
#
###
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
WORKDIR /work/
RUN chown 1001 /work \
    && chmod "g+rwX" /work \
    && chown 1001:root /work
COPY --chown=1001:root target/*-runner /work/application

EXPOSE 8080
USER 1001

CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]

As you can see, this Dockerfile uses the following application resources:

Next, I followed the instructions in the Dockerfile. By the way, the same steps are also described in the code guide.
[https://quarkus.io/guides/building-native-image#manually]

In order to build the native executable, I used the following command on the Linux Command Prompt:

mvn package -Pnative -Dquarkus.native.container-build=true

With the following output:

[INFO] Scanning for projects…
[INFO]
[INFO] ———————-< org.acme:getting-started >———————-
[INFO] Building getting-started 1.0-SNAPSHOT
[INFO] ——————————–[ jar ]———————————
[INFO]
[INFO] — quarkus-maven-plugin:1.7.0.Final:prepare (default) @ getting-started —
[INFO]
[INFO] — maven-resources-plugin:2.6:resources (default-resources) @ getting-started —
[INFO] Using ‘UTF-8’ encoding to copy filtered resources.
[INFO] Copying 4 resources
[INFO]
[INFO] — maven-compiler-plugin:3.8.1:compile (default-compile) @ getting-started —
[INFO] Nothing to compile – all classes are up to date
[INFO]
[INFO] — quarkus-maven-plugin:1.7.0.Final:prepare-tests (default) @ getting-started —
[INFO]
[INFO] — maven-resources-plugin:2.6:testResources (default-testResources) @ getting-started —
[INFO] Using ‘UTF-8’ encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /vagrant/applications/getting-started/src/test/resources
[INFO]
[INFO] — maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ getting-started —
[INFO] Nothing to compile – all classes are up to date
[INFO]
[INFO] — maven-surefire-plugin:3.0.0-M5:test (default-test) @ getting-started —
[INFO]
[INFO] ——————————————————-
[INFO] T E S T S
[INFO] ——————————————————-
[INFO] Running org.acme.getting.started.GreetingResourceTest
2020-08-30 10:49:52,067 INFO [io.quarkus] (main) Quarkus 1.7.0.Final on JVM started in 11.922s. Listening on: http://0.0.0.0:8081
2020-08-30 10:49:52,265 INFO [io.quarkus] (main) Profile test activated.
2020-08-30 10:49:52,266 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 23.889 s – in org.acme.getting.started.GreetingResourceTest
2020-08-30 10:50:01,782 INFO [io.quarkus] (main) Quarkus stopped in 0.109s
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] — maven-jar-plugin:2.4:jar (default-jar) @ getting-started —
[INFO]
[INFO] — quarkus-maven-plugin:1.7.0.Final:build (default) @ getting-started —
[INFO] [org.jboss.threads] JBoss Threads version 3.1.1.Final
[INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building native image source jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar/getting-started-1.0-SNAPSHOT-runner.jar
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Building native image from /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar/getting-started-1.0-SNAPSHOT-runner.jar
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Checking image status quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11
20.1.0-java11: Pulling from quarkus/ubi-quarkus-native-image
57de4da701b5: Already exists
cf0f3ebe9f53: Already exists
78512332cf2d: Pull complete
Digest: sha256:0b5f515bd2ac0a5d42534bc3332820d0226b0eae8b8f35d87fd225abd9a3ab23
Status: Downloaded newer image for quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11
quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Running Quarkus native-image plugin on GraalVM Version 20.1.0 (Java Version 11.0.7)
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] docker run -v /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar:/project:z –env LANG=C –user 1000:1000 –rm quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11 -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=1 -J-Duser.language=en -J-Dfile.encoding=UTF-8 –initialize-at-build-time= -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime -H:+JNI -jar getting-started-1.0-SNAPSHOT-runner.jar -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:EnableURLProtocols=http –no-server -H:-UseServiceLoaderFeature -H:+StackTrace getting-started-1.0-SNAPSHOT-runner
[getting-started-1.0-SNAPSHOT-runner:19] classlist: 11,794.35 ms, 0.96 GB
[getting-started-1.0-SNAPSHOT-runner:19] (cap): 1,753.72 ms, 0.94 GB
[getting-started-1.0-SNAPSHOT-runner:19] setup: 6,447.66 ms, 0.94 GB
10:54:14,423 INFO [org.jbo.threads] JBoss Threads version 3.1.1.Final
[getting-started-1.0-SNAPSHOT-runner:19] (clinit): 1,676.22 ms, 2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19] (typeflow): 53,897.19 ms, 2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19] (objects): 92,484.87 ms, 2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19] (features): 1,433.55 ms, 2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19] analysis: 152,230.05 ms, 2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19] universe: 4,297.09 ms, 2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19] (parse): 18,281.48 ms, 2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19] (inline): 17,095.20 ms, 2.85 GB
[getting-started-1.0-SNAPSHOT-runner:19] (compile): 98,601.71 ms, 2.64 GB
[getting-started-1.0-SNAPSHOT-runner:19] compile: 137,707.60 ms, 2.64 GB
[getting-started-1.0-SNAPSHOT-runner:19] image: 7,393.06 ms, 2.87 GB
[getting-started-1.0-SNAPSHOT-runner:19] write: 1,300.51 ms, 2.87 GB
[getting-started-1.0-SNAPSHOT-runner:19] [total]: 322,056.71 ms, 2.87 GB
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Execute [objcopy, –strip-debug, /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-runner]
[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 499945ms
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time: 09:09 min
[INFO] Finished at: 2020-08-30T10:58:24Z
[INFO] ————————————————————————
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

In order to build the image, I used the following command on the Linux Command Prompt:

docker build -f src/main/docker/Dockerfile.native -t quarkus/getting-started .

With the following output:


Sending build context to Docker daemon  49.56MB
Step 1/7 : FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
 —> 91d23a64fdf2
Step 2/7 : WORKDIR /work/
 —> Running in 5b16a3ec287a
Removing intermediate container 5b16a3ec287a
 —> 9798e17519ed
Step 3/7 : RUN chown 1001 /work     && chmod “g+rwX” /work     && chown 1001:root /work
 —> Running in c8e6d0d90e80
Removing intermediate container c8e6d0d90e80
 —> d044aa8c49c1
Step 4/7 : COPY –chown=1001:root target/*-runner /work/application
 —> d01372ad5bce
Step 5/7 : EXPOSE 8080
 —> Running in 0ab79da4d9d6
Removing intermediate container 0ab79da4d9d6
 —> 17d0a05e924f
Step 6/7 : USER 1001
 —> Running in 735b1fcd6f2f
Removing intermediate container 735b1fcd6f2f
 —> 5a4c711603b1
Step 7/7 : CMD [“./application”, “-Dquarkus.http.host=0.0.0.0”]
 —> Running in 13c2ce17e6f0
Removing intermediate container 13c2ce17e6f0
 —> 7f29ba864d85
Successfully built 7f29ba864d85
Successfully tagged quarkus/getting-started:latest
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

In order to get a list of all the docker images, I used the following command on the Linux Command Prompt:

docker image ls

With the following output:

Here you can see that image quarkus/getting-started:latest is created.

Remark:
See the Dockerfile and the option -t used in the docker build command (docker build -f src/main/docker/Dockerfile.native -t quarkus/getting-started .).
–tag , -t: Name and optionally a tag in the ‘name:tag’ format
[https://docs.docker.com/engine/reference/commandline/build/]

Next, in order to run the container, I used the following command on the Linux Command Prompt:

docker run -i --rm -p 8090:8090 quarkus/getting-started

Remark:
See the remark about using application HTTP port 8090 earlier in this article.

With the following output:



Powered by Quarkus 1.7.0.Final
2020-08-30 11:22:10,527 INFO  [io.quarkus] (main) getting-started 1.0-SNAPSHOT native (powered by Quarkus 1.7.0.Final) started in 0.015s. Listening on: http://0.0.0.0:8090
2020-08-30 11:22:10,527 INFO  [io.quarkus] (main) Profile prod activated.
2020-08-30 11:22:10,528 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]

Then, in the Web Browser on my Windows laptop, I entered the URL: http://localhost:8090/hello

And I got the following result:

So, running the application in a container using the produced native executable worked.

Creating a container using the container-image extensions

By far the easiest way to create a container-image from your Quarkus application is to leverage one of the container-image extensions.

If one of those extensions is present, then creating a container image for the native executable is essentially a matter of executing a single command:

./mvnw package -Pnative -Dquarkus.native.container-build=true -Dquarkus.container-image.build=true

Remark:

  • quarkus.native.container-build=true allows for creating a Linux executable without GraalVM being installed (and is only necessary if you don’t have GraalVM installed locally or your local operating system is not Linux)
  • quarkus.container-image.build=true instructs Quarkus to create a container-image using the final application artifact (which is the native executable in this case)

[https://quarkus.io/guides/building-native-image#using-the-container-image-extensions]

Remember from my previous article, the build is done using a container runtime. If the Quarkus config property quarkus.native.container-build is set, Docker will be used by default, unless container-runtime (by using property quarkus.native.container-runtime) is also set. In my demo environment I had Docker installed, so this is fine by me.
[https://technology.amis.nl/2020/09/01/quarkus-supersonic-subatomic-java-trying-out-some-quarkus-code-guides-part1/]

Quarkus provides extensions for building (and pushing) container images. Currently it supports:

  • Jib
  • Docker
  • S2I

Please see the documentation for more information about these different extensions.
[https://quarkus.io/guides/container-image]

Using the Docker container-image extension

Because in my demo environment I had Docker installed, I focused on the Docker container-image extension.

The extension quarkus-container-image-docker is using the Docker binary and the generated Dockerfiles under src/main/docker in order to perform Docker builds.
[https://quarkus.io/guides/container-image]

To use this feature, add the extension to your project. So, in order to add it, I used the following command on the Linux Command Prompt:

./mvnw quarkus:add-extension -Dextensions="container-image-docker"

With the following output:


[INFO] Scanning for projects…
[INFO]
[INFO] ———————-< org.acme:getting-started >———————-
[INFO] Building getting-started 1.0-SNAPSHOT
[INFO] ——————————–[ jar ]———————————
[INFO]
[INFO] — quarkus-maven-plugin:1.7.0.Final:add-extension (default-cli) @ getting-started —
✅ Extension io.quarkus:quarkus-container-image-docker has been installed
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time:  4.194 s
[INFO] Finished at: 2020-08-30T15:03:44Z
[INFO] ————————————————————————
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

In the pom.xml this added the following dependency:

    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-container-image-docker</artifactId>
    </dependency>

In order to get a list of all the docker images, I used the following command on the Linux Command Prompt:

docker image ls

With the following output:

In order to build the Docker image, I used the following command (mentioned earlier) on the Linux Command Prompt:

./mvnw package -Pnative -Dquarkus.native.container-build=true -Dquarkus.container-image.build=true

With the following output:


[INFO] Scanning for projects…
[INFO]
[INFO] ———————-< org.acme:getting-started >———————-
[INFO] Building getting-started 1.0-SNAPSHOT
[INFO] ——————————–[ jar ]———————————
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker/1.7.0.Final/quarkus-container-image-docker-1.7.0.Final.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker/1.7.0.Final/quarkus-container-image-docker-1.7.0.Final.pom (1.4 kB at 701 B/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker-parent/1.7.0.Final/quarkus-container-image-docker-parent-1.7.0.Final.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker-parent/1.7.0.Final/quarkus-container-image-docker-parent-1.7.0.Final.pom (741 B at 6.6 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-parent/1.7.0.Final/quarkus-container-image-parent-1.7.0.Final.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-parent/1.7.0.Final/quarkus-container-image-parent-1.7.0.Final.pom (933 B at 6.3 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker/1.7.0.Final/quarkus-container-image-docker-1.7.0.Final.jar
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker/1.7.0.Final/quarkus-container-image-docker-1.7.0.Final.jar (3.0 kB at 23 kB/s)
[INFO]
[INFO] — quarkus-maven-plugin:1.7.0.Final:prepare (default) @ getting-started —
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker-deployment/1.7.0.Final/quarkus-container-image-docker-deployment-1.7.0.Final.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker-deployment/1.7.0.Final/quarkus-container-image-docker-deployment-1.7.0.Final.pom (1.6 kB at 2.7 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-deployment/1.7.0.Final/quarkus-container-image-deployment-1.7.0.Final.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-deployment/1.7.0.Final/quarkus-container-image-deployment-1.7.0.Final.pom (1.9 kB at 17 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-spi/1.7.0.Final/quarkus-container-image-spi-1.7.0.Final.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-spi/1.7.0.Final/quarkus-container-image-spi-1.7.0.Final.pom (871 B at 7.4 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-util/1.7.0.Final/quarkus-container-image-util-1.7.0.Final.pom
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-util/1.7.0.Final/quarkus-container-image-util-1.7.0.Final.pom (642 B at 6.1 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-spi/1.7.0.Final/quarkus-container-image-spi-1.7.0.Final.jar
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-util/1.7.0.Final/quarkus-container-image-util-1.7.0.Final.jar
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-deployment/1.7.0.Final/quarkus-container-image-deployment-1.7.0.Final.jar
Downloading from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker-deployment/1.7.0.Final/quarkus-container-image-docker-deployment-1.7.0.Final.jar
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-util/1.7.0.Final/quarkus-container-image-util-1.7.0.Final.jar (3.6 kB at 7.7 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-spi/1.7.0.Final/quarkus-container-image-spi-1.7.0.Final.jar (6.5 kB at 8.9 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-deployment/1.7.0.Final/quarkus-container-image-deployment-1.7.0.Final.jar (11 kB at 15 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/io/quarkus/quarkus-container-image-docker-deployment/1.7.0.Final/quarkus-container-image-docker-deployment-1.7.0.Final.jar (21 kB at 27 kB/s)
[INFO]
[INFO] — maven-resources-plugin:2.6:resources (default-resources) @ getting-started —
[INFO] Using ‘UTF-8’ encoding to copy filtered resources.
[INFO] Copying 4 resources
[INFO]
[INFO] — maven-compiler-plugin:3.8.1:compile (default-compile) @ getting-started —
[INFO] Nothing to compile – all classes are up to date
[INFO]
[INFO] — quarkus-maven-plugin:1.7.0.Final:prepare-tests (default) @ getting-started —
[INFO]
[INFO] — maven-resources-plugin:2.6:testResources (default-testResources) @ getting-started —
[INFO] Using ‘UTF-8′ encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /vagrant/applications/getting-started/src/test/resources
[INFO]
[INFO] — maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ getting-started —
[INFO] Nothing to compile – all classes are up to date
[INFO]
[INFO] — maven-surefire-plugin:3.0.0-M5:test (default-test) @ getting-started —
[INFO]
[INFO] ——————————————————-
[INFO]  T E S T S
[INFO] ——————————————————-
[INFO] Running org.acme.getting.started.GreetingResourceTest
2020-09-01 18:50:03,249 INFO  [io.quarkus] (main) Quarkus 1.7.0.Final on JVM started in 11.691s. Listening on: http://0.0.0.0:8081
2020-09-01 18:50:03,261 INFO  [io.quarkus] (main) Profile test activated.
2020-09-01 18:50:03,262 INFO  [io.quarkus] (main) Installed features: [cdi, resteasy]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 33.676 s – in org.acme.getting.started.GreetingResourceTest
2020-09-01 18:50:13,067 INFO  [io.quarkus] (main) Quarkus stopped in 0.103s
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] — maven-jar-plugin:2.4:jar (default-jar) @ getting-started —
[INFO] Building jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT.jar
[INFO]
[INFO] — quarkus-maven-plugin:1.7.0.Final:build (default) @ getting-started —
[INFO] [org.jboss.threads] JBoss Threads version 3.1.1.Final
[INFO] [io.quarkus.deployment.pkg.steps.JarResultBuildStep] Building native image source jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar/getting-started-1.0-SNAPSHOT-runner.jar
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Building native image from /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar/getting-started-1.0-SNAPSHOT-runner.jar
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Checking image status quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11
20.1.0-java11: Pulling from quarkus/ubi-quarkus-native-image
Digest: sha256:0b5f515bd2ac0a5d42534bc3332820d0226b0eae8b8f35d87fd225abd9a3ab23
Status: Image is up to date for quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11
quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Running Quarkus native-image plugin on GraalVM Version 20.1.0 (Java Version 11.0.7)
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] docker run -v /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar:/project:z –env LANG=C –user 1000:1000 –rm quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11 -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=1 -J-Duser.language=en -J-Dfile.encoding=UTF-8 –initialize-at-build-time= -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime -H:+JNI -jar getting-started-1.0-SNAPSHOT-runner.jar -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:EnableURLProtocols=http –no-server -H:-UseServiceLoaderFeature -H:+StackTrace getting-started-1.0-SNAPSHOT-runner
[getting-started-1.0-SNAPSHOT-runner:19]    classlist:  29,007.23 ms,  0.96 GB
[getting-started-1.0-SNAPSHOT-runner:19]        (cap):   4,912.59 ms,  0.94 GB
[getting-started-1.0-SNAPSHOT-runner:19]        setup:  18,197.04 ms,  0.94 GB
18:54:16,535 INFO  [org.jbo.threads] JBoss Threads version 3.1.1.Final
[getting-started-1.0-SNAPSHOT-runner:19]     (clinit):   3,579.00 ms,  2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19]   (typeflow): 150,265.81 ms,  2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19]    (objects): 249,250.13 ms,  2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19]   (features):   3,833.43 ms,  2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19]     analysis: 413,141.58 ms,  2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19]     universe:  10,326.31 ms,  2.69 GB
[getting-started-1.0-SNAPSHOT-runner:19]      (parse):  61,713.93 ms,  2.71 GB
[getting-started-1.0-SNAPSHOT-runner:19]     (inline):  26,986.36 ms,  2.78 GB
[getting-started-1.0-SNAPSHOT-runner:19]    (compile): 284,875.97 ms,  3.25 GB
[getting-started-1.0-SNAPSHOT-runner:19]      compile: 382,876.95 ms,  3.25 GB
[getting-started-1.0-SNAPSHOT-runner:19]        image:  20,813.61 ms,  3.25 GB
[getting-started-1.0-SNAPSHOT-runner:19]        write:   2,789.28 ms,  3.25 GB
[getting-started-1.0-SNAPSHOT-runner:19]      [total]: 879,723.32 ms,  3.25 GB
[INFO] [io.quarkus.deployment.pkg.steps.NativeImageBuildStep] Execute [objcopy, –strip-debug, /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-runner]
[INFO] [io.quarkus.container.image.docker.deployment.DockerWorking] Docker daemon found. Version:’19.03.12’
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Starting docker image build
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Executing the following command to build docker image: ‘docker build -f /vagrant/applications/getting-started/src/main/docker/Dockerfile.native -t vagrant/getting-started:1.0-SNAPSHOT /vagrant/applications/getting-started’
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Sending build context to Docker daemon  50.82MB
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 1/7 : FROM registry.access.redhat.com/ubi8/ubi-minimal:8.1
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> 91d23a64fdf2
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 2/7 : WORKDIR /work/
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> 9798e17519ed
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 3/7 : RUN chown 1001 /work     && chmod “g+rwX” /work     && chown 1001:root /work
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> Using cache
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> d044aa8c49c1
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 4/7 : COPY –chown=1001:root target/*-runner /work/application
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> 9051879c623f
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 5/7 : EXPOSE 8080
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> Running in b80af8776a44
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container b80af8776a44
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> ff10cb14076e
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 6/7 : USER 1001
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> Running in 9f6ff323e89c
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container 9f6ff323e89c
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> 44d8ed57f354
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Step 7/7 : CMD [“./application”, “-Dquarkus.http.host=0.0.0.0”]
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> Running in 30e6130446d4
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Removing intermediate container 30e6130446d4
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor]  —> 9b131cd3181c
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully built 9b131cd3181c
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Successfully tagged vagrant/getting-started:1.0-SNAPSHOT
[INFO] [io.quarkus.container.image.docker.deployment.DockerProcessor] Built container image vagrant/getting-started:1.0-SNAPSHOT (9b131cd3181c)


[INFO] [io.quarkus.deployment.QuarkusAugmentor] Quarkus augmentation completed in 917108ms
[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time:  16:23 min
[INFO] Finished at: 2020-09-01T19:05:32Z
[INFO] ————————————————————————
vagrant@ubuntu-bionic:/vagrant/applications/getting-started$

For your and my convenience, in the table below I summarized the Quarkus deployment steps (io.quarkus.deployment.pkg.steps) from the output above:
[in bold, I highlighted the changes against the previous summarization]

Step Output
io.quarkus.deployment.pkg.steps.JarResultBuildStep Building native image source jar: /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar/getting-started-1.0-SNAPSHOT-runner.jar
io.quarkus.deployment.pkg.steps.NativeImageBuildStep Building native image from /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar/getting-started-1.0-SNAPSHOT-runner.jar
Checking image status quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11 20.1.0-java11: Pulling from quarkus/ubi-quarkus-native-image Digest: sha256:0b5f515bd2ac0a5d42534bc3332820d0226b0eae8b8f35d87fd225abd9a3ab23 Status: Image is up to date for quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11 quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11
Running Quarkus native-image plugin on GraalVM Version 20.1.0 (Java Version 11.0.7)
docker run -v /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-native-image-source-jar:/project:z --env LANG=C --user 1000:1000 --rm quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11 -J-Djava.util.logging.manager=org.jboss.logmanager.LogManager -J-Dsun.nio.ch.maxUpdateArraySize=100 -J-Dvertx.logger-delegate-factory-class-name=io.quarkus.vertx.core.runtime.VertxLogDelegateFactory -J-Dvertx.disableDnsResolver=true -J-Dio.netty.leakDetection.level=DISABLED -J-Dio.netty.allocator.maxOrder=1 -J-Duser.language=en -J-Dfile.encoding=UTF-8 --initialize-at-build-time= -H:InitialCollectionPolicy=com.oracle.svm.core.genscavenge.CollectionPolicy$BySpaceAndTime -H:+JNI -jar getting-started-1.0-SNAPSHOT-runner.jar -H:FallbackThreshold=0 -H:+ReportExceptionStackTraces -H:-AddAllCharsets -H:EnableURLProtocols=http --no-server -H:-UseServiceLoaderFeature -H:+StackTrace getting-started-1.0-SNAPSHOT-runner
Execute [objcopy, --strip-debug, /vagrant/applications/getting-started/target/getting-started-1.0-SNAPSHOT-runner]

As you can see in the output above, for creating the native executable, the following docker image is used:

quay.io/quarkus/ubi-quarkus-native-image:20.1.0-java11

In order to get a list of all the docker images, I used the following command on the Linux Command Prompt:

docker image ls

With the following output:

Here you can see that image vagrant/getting-started:1.0-SNAPSHOT is created.

Remark:
This name is different from the one we got before, while executing these steps manually (via: docker build -f src/main/docker/Dockerfile.native -t quarkus/getting-started .).

You can see, from the output above that the following command was used to build the docker image:

Executing the following command to build docker image: ‘docker build -f /vagrant/applications/getting-started/src/main/docker/Dockerfile.native -t vagrant/getting-started:1.0-SNAPSHOT /vagrant/applications/getting-started’

So, let’s figure out why this image name and tag was used.

If you want to customize the container image build process, you can use several properties. Please see the documentation.
[https://quarkus.io/guides/container-image#customizing]

With regard to the image name and tag, the following properties are used:

Remark:
In addition to the generic container image options, the container-image-docker also provides some options. Please see the documentation.
[https://quarkus.io/guides/container-image#customizing]

In the example application.properties, I created earlier (described in my previous article), I could see that the image name defaults to the name of the project and the version defaults to the version of the project.
[https://technology.amis.nl/2020/09/01/quarkus-supersonic-subatomic-java-trying-out-some-quarkus-code-guides-part1/]

#
# The name of the application.
# If not set, defaults to the name of the project (except for tests where it is not set at all).
#
#quarkus.application.name=

#
# The version of the application.
# If not set, defaults to the version of the project (except for tests where it is not set at all).
#
#quarkus.application.version=

Remember the contents of pom.xml is:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.acme</groupId>
  <artifactId>getting-started</artifactId>
  <version>1.0-SNAPSHOT</version>
...
</project>

So, putting it all together: <user>/<name of the project>:<version of the project >

This explains the image name and tag: vagrant/getting-started:1.0-SNAPSHOT

Remark:
A Docker image name can be made up of slash-separated name components.

So, I conclude this article. I shared with you the steps I took trying out the Quarkus code guide “Building a Native Executable”, and more specific the steps related to the topic “Creating a container”. I described how you can create a container manually, using the JAR produced by the Quarkus Maven Plugin or by using a produced native executable.

By far the easiest way to create a container-image from your Quarkus application is to leverage one of the container-image extensions, like the one I used, the Docker container-image extension.

In a next article, you can read more about another Quarkus code guide I tried out, related to the following topic:

  • The ability to automatically generate Kubernetes resources by Quarkus

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Next Post

My Steps for Getting Started with Java Development on Windows

Facebook0TwitterLinkedinIn this article a brief overview of my steps to set up an environment on my Windows 10 laptop for doing Java programming. If you follow these steps, you should be up and running with coding, building, testing and packaging Java applications on your laptop in some 20 minutes. The […]