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
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:
- target/lib/*
- target/*-runner.jar (in our case this is: getting-started-1.0-SNAPSHOT-runner.jar)
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):
(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
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:
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:
- target/*-runner (in our case this is: getting-started-1.0-SNAPSHOT-runner)
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:
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:
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:
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] [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]
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:
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:
- quarkus.container-image.group The group the container image will be part of. If not set defaults to: ${user.name} (being the the system user name)
- quarkus.container-image.name The name of the container image. If not set defaults to: ${quarkus.application.name:unset}
- quarkus.container-image.tag The tag of the container image. If not set defaults to: ${quarkus.application.version:latest}
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