DEV Community

Biswarup Adhikari
Biswarup Adhikari

Posted on

Streamlining React App Deployments: Overcoming Docker Build Args Limitations with `env-config.js`

When deploying React applications or any javascript based frontend applications such as Angular, Vuejs etc across various environments like development, staging, and production, developers often face a common challenge with Docker: the limitations of build arguments (--build-arg). Build arguments are frequently used to pass environment-specific configurations to a Docker image at build time. However, this approach hardcodes the values into the image, reducing flexibility and requiring separate builds for each environment. This article explores an alternative strategy using env-config.js, enhancing the reusability and flexibility of Docker images across different environments.

Understanding the Problem with Docker Build Args

Docker's build arguments allow you to pass configuration during the image build process. For instance:

ARG REACT_APP_API_URL
ENV REACT_APP_API_URL=$REACT_APP_API_URL
Enter fullscreen mode Exit fullscreen mode

While this method is effective for injecting environment variables into the Docker image, it has a significant drawback. The variables become hardcoded into the image. As a result, the same image cannot be reused across different environments (dev, staging, prod) without rebuilding it for each one. This leads to a lack of flexibility and increased complexity in your CI/CD pipeline.

The Solution: env-config.js

A more flexible approach involves using a JavaScript file, env-config.js, generated dynamically at runtime. This file is created using a bash script and loaded before your React application starts:

#!/bin/bash
echo "window._env_ = {" > /var/www/html/env-config.js
echo "  REACT_APP_API_URL: \"${REACT_APP_API_URL}\"" >> /var/www/html/env-config.js
echo "}" >> /var/www/html/env-config.js
Enter fullscreen mode Exit fullscreen mode

With this setup, the environment variables are not hardcoded into the Docker image. Instead, they are injected at runtime, allowing the same image to be used across multiple environments.

Integrating env-config.js with Docker

Here's how to configure the Dockerfile for this approach:

# Build stage for React app
FROM node:latest as build
WORKDIR /app
COPY package.json ./
COPY yarn.lock ./
RUN yarn install
COPY . ./
RUN yarn build

# Nginx stage
FROM nginx:alpine
COPY --from=build /app/build /var/www/html
COPY env-to-js.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/env-to-js.sh
CMD ["/bin/sh", "-c", "/usr/local/bin/env-to-js.sh && nginx -g 'daemon off;'"]
Enter fullscreen mode Exit fullscreen mode

This Dockerfile builds the React app and sets up Nginx to serve it. The critical addition is the env-to-js.sh script that generates env-config.js at container startup, injecting the current environment's variables.

Accessing Environment Variables in React

In your React application, access these variables from the global window object:

const apiUrl = window._env_.REACT_APP_API_URL || 'default-api-url';
Enter fullscreen mode Exit fullscreen mode

Security Considerations

It’s important to note that any information in env-config.js is publicly visible. Be cautious not to include sensitive data like private API keys, secrets etc. Treat env-config.js as a publicly accessible resource.

Conclusion: Enhanced Flexibility and Reusability

By adopting the env-config.js strategy in your Dockerized React application, you achieve significant flexibility. This approach allows you to use the same Docker image across various environments without the need for separate builds, simplifying your deployment process and enhancing maintainability.

Top comments (0)