AI, Machine Learning, DevOps

Modifying environment variables in dockerized front-end application

How can I change the environment variable in my dockerized front-end React application without rebuilding the Docker image? What if I simply need to change the API URL environment variable?

Docker React GCP

These might be the questions you face during your developing journey.

When building a container for modern apps (for example, in React, Angular or Vue.js), you have to be able to change configuration settings based on where the container runs. One of the most common modifications would be the API URL depending on the stage of the front-end application.

In our case we had a legacy dockerized Front-End React App on Google Cloud Run node. This app was sending the API requests to the API gateway URL.

What we needed was to modify this URL as environment variable in Front-End container and simply redeploy the container without rebuilding. It was important for us as building that Front-End docker container was take more time than normally due to some technical limitations we had in the legacy React app.


Where the problem comes from

Let’s take a look how most of the Docker containers for React Apps served through Nginx are built (I’ve removed some steps from the code for simplicity):

FROM node:16-alpine as builder   
WORKDIR /var/www/clientapp\_frontend   
COPY package.json .  
RUN npm install  
COPY . .  
_\# two lines below to make FLASK\_API\_URL settable via --build-arg in docker build command_  
ARG BUILDTIME\_FLASK\_API\_URL='some\_fallback\_default\_URL'  
ENV FLASK\_API\_URL=$BUILDTIME\_FLASK\_API  
RUN npm run build_\# taking the dist build from the previous builder container and using it in a nginx container_ 
FROM nginx:1.17-alpine  
COPY — from=builder /var/www/clientapp\_frontend/build/ /usr/share/nginx/html  
COPY — from=builder /var/www/clientapp\_frontend/nginx\_entrypoint.sh ./nginx\_entrypoint.sh  
EXPOSE $FRONTEND\_PORT  
ENTRYPOINT /bin/sh -x ./nginx\_entrypoint.sh && nginx -g ‘daemon off;’

As you can see there’s an environment variable FLASK_API_URL provided during building. However, what many articles about building a React App in Nginx with Docker miss mentioning is that it’s not possible to override such environment variable at runtime since its runtime is the client’s browser. In other words, this FLAKS_API_URL value gets hardcoded in the JS bundle.


Solution

There is a possibility to inject environment variables at the moment when the container starts. These environment variables are to be written in some JS file and served by Nginx with a <script> tag inside index.html

Check my nginx_entrypoint.sh file in my GitHub repository for the full code to see how I inject environment variables at runtime generating JS script env-config.js and inserting it to index.html with bash.

  • FLASK_API_URL env varianle is read and placed into .env file.
env\_content=’FLASK\_API\_URL=${FLASK\_API\_URL}’printf “$env\_content” > /usr/share/nginx/html/.env
  • Then all environment variables are read from .env file and saved in JS script env-config.js
echo “window.\_env\_ = {“ > /usr/share/nginx/html/env-config.jsawk -F ‘=’ ‘{ print $1 “: \\”” (ENVIRON\[$1\] ? ENVIRON\[$1\] : $2) “\\”,” }’ /usr/share/nginx/html/.env >> /usr/share/nginx/html/env-config.jsecho “}” >> /usr/share/nginx/html/env-config.js
  • At the end of the file this JS script is placed inside index.html, so the React App can digest these environment variables.
sed -i.bak ‘s~<body\[^>\]\*>~&<script src=”env-config.js”></script>~’ /usr/share/nginx/html/index.html



See the full code of it my GitHub repository

https://github.com/iskandre/dockerized-react-env-variables

GitHub - iskandre/dockerized-react-env-variables: A simple example demonstrating a Dockerfile for React app served by Nginx and how to inject runtime env variables to React when starting the docker container

A simple example demonstrating a Dockerfile for React app served by Nginx and how to inject runtime env variables to React when starting the docker container - GitHub - iskandre/dockerized-react-e...

Thanks for reading.

I hope this will be a help and feel free to share your thoughts, suggestions or ask any questions.