skip to Main Content

I have a React app that connects to a single backend API. Now I want to build a single Docker image and pass different API URLs as variables in the config.ts file depending on different environments like dev, uat, and prod during container at runtime.

I tried using process.env and REACT_APP variables, but it seems they do not reflect at runtime. Any suggestion?

However, I am using Docker compose for creating Docker Containers.

2

Answers


  1. If you’re building the app into your image, then no – it’s the build phase that "bakes" process.env.REACT_APP_WHATEVER into constant strings into the static .js bundles, based on the environment value at build time. There is, after all, no such thing as process.env (or an environment variable) in a browser.

    Unless you want to also run a backend that would serve runtime values for this configuration, it could be easier to make this config.ts of yours react to e.g. a query parameter, a local storage setting, etc., and determine the URLs based on it, e.g.

    function getEnvironment() {
      return localStorage.get("environment") ?? "production";
    }
    export function getAPIURL() {
      switch(getEnvironment()) {
        case "dev":
          return "http://127.0.0.1:8181";
        default:
          return process.env.REACT_APP_WHATEVER;  // baked at build time
      }
    }
    

    and then set up a way to store the environment value in whichever storage you choose.

    Login or Signup to reply.
  2. Any change in the backend URL necessitated a manual code update and redeployment, which was time-consuming and error-prone.

    Deployment scenarios like Kubernetes, where backend URLs are not predetermined, demanded a more dynamic configuration method.

    A Step Towards Flexibility: Config.js

    To overcome these hurdles, we proposed defining all backend URLs in a Config.js file within the React project. By using variables from Config.js throughout the code, we could build and deploy the project using Nginx or Tomcat, thus centralizing URL management and simplifying changes.

    Pros:

    Centralized URL management reduces boilerplate code and simplifies updates.

    Cons:

    Separate builds and deployments are required for each environment (Test, Development, Production), each needing a unique Config.js.

    window.env = {

    REACT_APP_URL:"http://localhost",

    REACT_APP_API_URL: "default",

    REACT_APP_VEHICLE_IMAGE_URL: "default",

    REACT_APP_NAME: " default",

    }

    Streamlining Deployment: Environment-Specific Hardcoding

    We refined our approach by building the React project once with default values in Config.js. During deployment, we would create copies of the build and modify the Config.js file in each to include environment-specific backend URLs.

    Cons:

    This method still involved manual editing of Config.js, introducing the risk of errors and additional deployment steps.

    The Docker-Based Solution

    Our next iteration utilized Docker for deploying the build to Nginx or Tomcat. We included a script in the Dockerfile that used “echo” statements (with parameter name hardcoded and value as a placeholder), allowing for dynamic URL configuration during the Docker Compose process. Once the image is created, the actual values can be passed during the container startup.

    Cons:

    We encountered issues with Docker not correctly reading the script file during the container startup, leading to inconsistencies in URL configuration.

    The Final Approach: Embedded Scripting

    Continuing with Docker for deployment, we embedded the necessary script directly within the Docker image. This ensured that dynamic values and runtime URL configurations were properly set, addressing the previous issues and streamlining the deployment process.

    Use the official NGINX base image

    FROM nginx: latest

    Copy your React build files to the NGINX static content folder

    COPY application/build/ /usr/share/nginx/html/build

    ENV BACKEND_URL ‘default’
    ENV APP_NAME ‘default’

    RUN touch /usr/share/nginx/scripts/set_env.sh
    RUN echo "#!/bin/bashn
    n
    echo $1n
    echo $2n

    Check if REACT_APP_URL is provided as an environment variablen

    if [ -z $1 ]n
    thenn
    echo "Error: BACKEND_URL environment variable not set."n
    exit 1 n
    fi n
    n
    if [ -z $2 ] n
    then n
    echo "Error: APP_NAME environment variable not set." n
    exit 1 n
    fi n
    echo "window.env = { REACT_APP_URL: ‘$1’, REACT_APP_API_URL: ‘default’, REACT_APP_VEHICLE_IMAGE_URL: ‘default’, REACT_APP_NAME: ‘$2’ };" > /usr/share/nginx/html/build/config.js n
    " > /usr/share/nginx/scripts/set_env.sh

    Make the script executable

    RUN chmod +x /usr/share/nginx/scripts/set_env.sh

    Start NGINX

    CMD ["/bin/sh", "-c", "/usr/share/nginx/scripts/set_env.sh ${BACKEND_URL} ${APP_NAME}} && nginx -g ‘daemon off;’"]

    Conclusion

    By adopting this final solution, we have created a more reliable and automated configuration process for environment-specific URLs. This reduces the risk of manual errors and ensures a smooth and efficient deployment workflow, allowing our React UI to dynamically connect with various backend services.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search