This blog post addresses the topic, how to use environment variables to make a containized Quarkus application more flexible. We will touch following technologies Quarkus, OpenJ9 Java runtime, MicroProfile, Dockerfile definition and Code Engine.
When you run a containerized application on a container orchestration platform like Kubernetes, Open Shift or with a serverless framework like Knative or Code Engine or on other platforms, it is helpful to pass endpoints to other applications to the containerized application by using environment variables. When the container will be restarted, these variables can be provided to the container and no adjustment in the source code is necessary. You can use configmaps or in Code Engine simple the environment variable itself.
We will follow along an application example for the implementation and the example source code you find in the Get started to deploy a Java Microservices application to Code Engine workshop. (or the direct link to the used file in the GitHub repository is provided in the blog post itself)
Start with the architecture of the example application
The following diagram shows the architecture of the example application, that runs on Code Engine. There is a web-app
frontend application that serves the Javascript/Vue.js code to the browser. The web-app
code running in the browser invokes a REST API of the web-api
microservice. The web-api
microservice in turn invokes a REST API of the articles
microservice. Keycloak
is used for the Identity and Access Management
of that microservices based application. To see the results in the web application, users need to be authenticated and they need to have the role user
.

Focus on one Microservice
In this blog post we will only focus on the implementation for the usage of the environment variables for the web-api microservice.

The web-api microservice uses two external endpoints internally to consume information, one to Keycloak and one to the articles microsservice. The Keycloak endpoint is managed by Quarkus with it’s OpenID Connect implementation. (Quarkus is OpenID Connect compliant). We will focus on the connection to the articels microsservice.
There for we will cover following topics in a row:
- Configuration of
application.properties
file of Quarkus - Usage of the annotation @ConfigProperty in the Java class
- Invocation of the Quarkus Java application with the needed environment variables as parameters
- Write a Dockerfile and use a
docker_entrypoint_*.sh
file - Run a Docker container with the environment variables locally
- Deploy the application example with the Code Engine command line, including the environment variables
CONFIGRATION OF APPLICATION.PROPERTIES
FILE¶
The configuration src/resources/application.properties
file contains configurations for your Quarkus application, some of them are predefined and you can define your own configurations, for more details visit the example Quarkus – Configuring your application.
In our case we only focus on these two properties quarkus.oidc.auth-server-url
and cns.articles-url
.
For both properties configurations we define the usage as you see in the following code: Using the environment variable value or if this value is not available use the default value.
${ENVIRONMENT_VARIABLE:"default-value"}
.
...
quarkus.oidc.auth-server-url=${QUARKUS_OIDC_AUTH_SERVER_URL:"http://localhost:8282/auth/realms/quarkus"}
...
cns.articles-url=${CNS_ARTICLES_URL:"http://localhost:8082/articles"}
USAGE OF THE ANNOTATION @CONFIGPROPERTY¶
The following code extract of the ArticlesDataAccess.java
class of the example shows the needed import from MicroProfile . With the @ConfigProperty
annotation you can access the value of the environment variable and pass that value to the articles_url variable.
import org.eclipse.microprofile.config.inject.ConfigProperty;
@ApplicationScoped
public class ArticlesDataAccess {
@ConfigProperty(name = "cns.articles-url")
private String articles_url;
INVOCATION OF THE QUAKUS JAVA APPLICATION¶
Now we need to provide the environment variables to the Quarkus application for the startup, we do that with the -D commandline parameter for our custom environment variable. The following code is an extract of the docker_entrypoint_start-quarkus.sh
bash file. The bash script is used for Java startup inside the Dockerfile
and contains following Java command.
java -Xmx128m \
-Xscmaxaot100m \
-XX:+IdleTuningGcOnIdle \
-Xtune:virtualized \
-Xscmx128m \
-Xshareclasses:cacheDir=/opt/shareclasses \
-Dcns.articles-url=${CNS_ARTICLES_URL} \
-jar \
/opt/app/app.jar
In the following code you see the invocation of the docker_entrypoint_start-quarkus.sh
bash script in the Dockerfile
and you see we use OpenJ9 as our the Java runtime for the container.
...
FROM adoptopenjdk/openjdk11-openj9:ubi-minimal
...
# Environment variables
COPY ./docker_entrypoint_start-quarkus.sh ./docker_entrypoint_start-quarkus.sh
RUN chmod 777 docker_entrypoint_start-quarkus.sh
EXPOSE 8081
CMD ["/bin/sh","docker_entrypoint_start-quarkus.sh"]
RUN THE CONTAINER LOCALLY¶
Now we can start the container locally to verify does it work and pass the needed environment variables to the container, which are consumed by the Quarkus microservices application web-api.
export REPOSITORY=tsuedbroecker
docker run -it -p 8080:8081 -e CNS_ARTICLES_URL="http://localhost:8082/articles" -e QUARKUS_OIDC_AUTH_SERVER_URL="http://localhost:8282/auth/realms/quarkus" "quay.io/$REPOSITORY/web-api-ce:v5"
DEPLOY TO CODE ENGINE
¶
When we deploy the application to Code Engine
we can simply pass the environment variables using the CLI and we don’t need to define an additional configmap as for Kubernetes, Open Shift or Knative.
ibmcloud ce application create --name web-api \
--image "quay.io/$REPOSITORY/web-api-ce:v6" \
--cpu 1 \
--env QUARKUS_OIDC_AUTH_SERVER_URL="$KEYCLOAK_URL/auth/realms/quarkus" \
--env CNS_ARTICLES_URL="http://articles.$NAMESPACE.svc.cluster.local/articles" \
--max-scale 1 \
--memory 2G \
--min-scale 0 \
--port 8081
Summary¶
With the combination of Quarkus, OpenJ9 Java runtime, MicroProfile, Dockerfile definition and Code Engine it’s pretty easy to pass environment variables to a containerized application.
I hope this was useful for you and let’s see what’s next?
Greetings,
Thomas
#Java, #codeengine, #microprofile, #Docker, #container, #quarkus, #environment