This blog post addresses the topic, how to use environment variables to make a containerized Vue.js frontend application more flexible. We will touch following technologies Vue.js, NGINX, JavaScript, Dockerfile and Code Engine.
When you run a containerized application on a container orchestration platform like Kubernetes, Open Shift or on a serverless frameworks like Knative or Code Engine or other platforms, it’s 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 simply the environment variable itself.
The example source code you find in this workshop.
In addition, it’s useful when you take a look into this awesome blog post: Externalise and Configure Frontend Environment Variables on Kubernetes which was used for the starting point for the configuration.
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 THE FRONTEND APPLICATION¶
We will focus on the implementation of the web-app frontend, where we use environment variables to define the container configuration at the startup of the container. Therefor we need to understand some of the implementation in Vue.js and configuration of the NGINX webserver.
The image below shows the part of the architecture we focus on.

The web-app fronted uses two endpoints to consume information, one is Keycloak and one is the web-api microsservice. We need two environment variables for that. In additional we want to be flexible in the route definition for the web fronted and therefore we define one additional environment variable for the application route.
Therefore, we will cover following topics in a row:
- Define global variables in JavaScript.
- Use of the global variable to define a custom route for the frontend.
- Use of the global variable to set the endpoints for Keycloak and the web-api microservice.
- Configuration of the NGINX server
- Automatic creation of the file for the global variables using a bash script.
- Definition of a
docker_entrypoint.sh
bash script. - Definition of the
Dockerfile
for the container. - Run the container
locally
. - Deploy to
Code Engine
.
Define global variables in JavaScript¶
First we define the global variables using window.variableName
. This global variables in that file can be used later to be generated using the values from environment variables. To make this flexible we need to generate this file with the value of the environment variables, when the container will be restarted by any container management or serverless framework. Later we will implement the creation of the file by using a bash script.
The web application will be loaded in the browser, so we need to ensure that the global variables are available during the execution of the web application. Therefor we will save the configuration env-config.js
file in the public folder, which will be loaded into the browser.
This is the example code webapp/public/env-config.js
.
window.VUE_APP_ROOT="/"
window.VUE_APP_KEYCLOAK="http://localhost:8282/auth"
window.VUE_APP_WEBAPI="http://localhost:8081/"
You need to add also the resource file webapp/public/env-config.js
information to the webapp/public/index.html file.
<!-- used as 'environment' variables, when we going to deploy to OpenShift-->
<script src="env-config.js" type="text/javascript"></script>
<!-- used as 'environment' variables, when we going to deploy to OpenShift-->
Use of the global variable to define a custom route for the frontend¶
To be flexible to run multiple different configurations for different instances of the example application on the same OpenShift cluster, we need to define different routes for those different instances, to avoid an overlap. The route definition happens in the webapp/src/router.js
file. For more details, please visit Vue.js
In the example code you see the definition of the path with the window.VUE_APP_ROOT variable.
...
export default new Router({
mode: 'history',
routes: [
{
path: window.VUE_APP_ROOT,
name: 'home',
component: Home
}
],
});
...
Use of the global variable to set the endpoints for Keycloak and the web-api microservice.¶
The following code shows, where we use the window.VUE_APP_KEYCLOAK
and window.VUE_APP_WEBAPI
variables defined in the env-config.js
file to set the endpoints for the web-api and Keycloak. You find the code example here webapp/src/main.js
.
...
else {
console.log("--> log: option 2");
let keycloakUrl = window.VUE_APP_KEYCLOAK;
let webapiUrl = window.VUE_APP_WEBAPI;
let cnsRedirectUrl = 'https://' + currentHostname + window.VUE_APP_ROOT; // logout
urls = {
api: webapiUrl,
login: keycloakUrl,
cns: cnsRedirectUrl
}
console.log("--> log: urls ", urls);
store.commit("setAPIAndLogin", urls);
}
...
Configuration of the NGINX webserver¶
To provide the needed web application resources to a browser for our web-app container, we use a NGINX webserver. We need to ensure that the file webapp/public/env-config.js
is available in the public folder, that our web application can access the values in the browser instance.
In addition, we need to define the usage of a different port than 80 for the NGINX webserver, because we would like to run the container for example on OpenShift. Here we are only allowed to run NGINX as non-root application. Here you find a useful blog posts related to that topic, one made by Josf Bilka and one available on OpenShift blog post at Red Hat deploy Vue.js applications on OpenShift
.
We need to change the configuration for the NGINX webserver. Here you find the example source code.
# nginx.conf
worker_processes auto;
# customization
daemon off;
user nginxuser;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
client_body_temp_path /tmp/client_temp;
proxy_temp_path /tmp/proxy_temp_path;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
server {
listen 8080;
charset utf-8;
sendfile on;
server_name _;
index index.html;
error_log /tmp/error.log;
access_log /tmp/access.log;
location / {
root /code;
expires -1;
add_header Pragma "no-cache";
add_header Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0";
try_files $uri /index.html = 404;
}
}
}
Automatic creation of the file for the global variables¶
We use a bash script for the automatic creation of the file for the global variables. You find the example file here generate_env-config.sh
. Therefor we will use the environment variables, which we provide the container later during the invocation based on the environment variables given by the Docker run command using the -e
parameter VUE_APP_ROOT
,VUE_APP_KEYCLOAK
and VUE_APP_WEBAPI
.
########################################
cat <<EOF
window.VUE_APP_ROOT="${VUE_APP_ROOT}"
window.VUE_APP_KEYCLOAK="${VUE_APP_KEYCLOAK}"
window.VUE_APP_WEBAPI="${VUE_APP_WEBAPI}"
EOF
Definition of a docker_entrypoint.sh
bash script¶
We define a docker_entrypoint.sh
bash script, which helps us to run all needed steps during the startup of the container in a structed and controlled way. Bash script to start the ngnix server and to create a env-config.js
file. You find the example source code here webapp/docker_entrypoint.sh
. The script also contains more steps we can use for the verification during the startup of the container.
The is extract of the example code which creates the needed file in our container in the NGINX webserver public folder.
...
"/bin/sh" ./generate_env-config.sh > ./code/env-config.js
nginx
...
Definition of the Dockerfile
for the container¶
You find the example Dockerfile
here webapp/Dockerfile.os4-webapp
. As you see we start the container with the command CMD ["/bin/sh","docker_entrypoint.sh"]
and we expose the port 8080
. We create a new user nginxuser
and provide the needed rights to access the folders and files we need to access during the startup of the container, but we will not run the container as root.
...
##############################
# PRODUCTION
##############################
FROM nginx:1.20.0-alpine
RUN apk add --update coreutils
# Add a user how will have the rights to change the files in code
RUN addgroup -g 1500 nginxusers
RUN adduser --disabled-password -u 1501 nginxuser nginxusers
# Configure ngnix server
COPY nginx-os4-webapp.conf /etc/nginx/nginx.conf
WORKDIR /code
COPY --from=BUILD /usr/src/app/dist .
# Configure web-app for environment variable usage
WORKDIR /
COPY docker_entrypoint.sh .
COPY generate_env-config.sh .
RUN chown nginxuser:nginxusers docker_entrypoint.sh
RUN chown nginxuser:nginxusers generate_env-config.sh
RUN chmod 777 docker_entrypoint.sh generate_env-config.sh
RUN chown -R nginxuser:nginxusers /code
RUN chown -R nginxuser:nginxusers /etc/nginx
RUN chown -R nginxuser:nginxusers /tmp
RUN chmod 777 /code
RUN chmod 777 /tmp
RUN chmod 777 /etc/nginx
USER nginxuser
EXPOSE 8080:8080
CMD ["/bin/sh","docker_entrypoint.sh"]
RUN THE CONTAINER LOCALLY¶¶
Now we can build and run the container locally to verify does it work and pass the needed environment variables to the container, which are consumed by the Vue.js frontend application web-app.
- build
docker build -t "quay.io/$REPOSITORY/web-app-ce:v2" -f Dockerfile.os4-webapp .
- run locally
docker run -it -p 8080:8080 -e VUE_APP_ROOT="/" -e VUE_APP_KEYCLOAK="http://localhost:8282/auth" -e VUE_APP_WEBAPI="localhost" "quay.io/tsuedbroecker/web-app-secure-https:v2"
DEPLOY TO CODE ENGINE¶
When we deploy the application to Code Engine, we can simply pass the environment variables using the Code Engine CLI and we don’t need to define an additional configmap as we would need in Kubernetes, Open Shift or Knative.
This is the Code Engine CLI
command used in the bash script you can find here, which is used to deploy the example application.
ibmcloud ce application create --name web-app \
--image "quay.io/$REPOSITORY/web-app-ce:v2" \
--cpu 0.5 \
--memory 1G \
--env VUE_APP_KEYCLOAK="$KEYCLOAK_URL/auth" \
--env VUE_APP_ROOT="/" \
--env VUE_APP_WEBAPI="$WEBAPI_URL/articles" \
--max-scale 1 \
--min-scale 0 \
--port 8080
Summary¶
When you going to use environment variables to make a Vue.js containerized application flexible to deploy to Code Engine
, you need to understand following technologies Vue.js, NGINX, JavaScript, Dockerfile and Code Engine. That combination to makes your Vue.js frontend more flexible, when you run the fronted as a containerized application in a serverless framework environment and you want to configure different dependencies or configurations of your application, without building a new version of your application. Once again, we used successfully the environment variables for the containers, it was also helpful in my last blog post related to the Quarkus application example.
I hope this was useful for you and let’s see what’s next?
Greetings,
Thomas
#JavaScript, #codeengine, #NGNIX, #Docker, #container, #vuejs, #environment
Leave a Reply