DEV Community

Cover image for Injecting Environment Variables in a Frontend Rollup Build (with Docker)
Athreya aka Maneshwar
Athreya aka Maneshwar

Posted on

3 2 2 2 2

Injecting Environment Variables in a Frontend Rollup Build (with Docker)

Hi there! I'm Maneshwar. Right now, I’m building LiveAPI, a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. LiveAPI makes it easier to discover, understand, and interact with APIs in large infrastructures.


When you're building a frontend app—especially one that talks to multiple APIs or needs environment-specific values—you’ll likely want to inject these variables at build time, not runtime.

This is especially true if you're using a bundler like Rollup (instead of Vite/Webpack). Here's how to do it cleanly using Docker, .env, and Rollup.

Problem

Frontend code can’t access environment variables at runtime like a backend can. There’s no process.env available in the browser. So if you're trying to do:

const baseURL = process.env.PARSE_BASE;
Enter fullscreen mode Exit fullscreen mode

This only works if Rollup replaces that with an actual string during build time.

Solution: Replace process.env.* at Build Time

Use @rollup/plugin-replace to replace environment variables during the build. The trick is to load values from your .env file and inject them into both your client and server bundles.

Example Project Structure

We're working with a frontend that:

  • Is built with Rollup
  • Has SSR output
  • Needs Authentik and Parse variables at build time

Here’s how it’s wired together.

Sample .env file

ROLLUP_WATCH=true

PARSE_BASE="http://localhost:1337/parse"
PARSE_APP_ID=parse
PARSE_MASTER_KEY=parse
PARSE_APP_NAME=parse

AUTHENTIK_BASE_URL="http://localhost:9000"
AUTHENTIK_CLIENT_ID="abc123"
AUTHENTIK_CLIENT_SECRET="secret"
AUTHENTIK_REDIRECT_URI="http://localhost:3000/signin/auth/index.html"
Enter fullscreen mode Exit fullscreen mode

rollup.config.js — Injecting the values

import replace from '@rollup/plugin-replace';
import dotenv from 'dotenv';
dotenv.config();

const envReplacements = {
  preventAssignment: true,
  'process.env.PARSE_BASE': JSON.stringify(process.env.PARSE_BASE),
  'process.env.AUTHENTIK_BASE_URL': JSON.stringify(process.env.AUTHENTIK_BASE_URL),
  // Add all others similarly...
};

export default {
  // ...
  plugins: [
    // other plugins...
    replace(envReplacements)
  ]
};
Enter fullscreen mode Exit fullscreen mode

This tells Rollup: "Wherever you see process.env.XYZ, replace it with the actual value."

Dockerfile — Pass values in via ARG

FROM node:18

ARG PARSE_BASE
ARG AUTHENTIK_CLIENT_ID
# etc...

WORKDIR /app

# Create .env file dynamically
RUN echo "VITE_PARSE_BASE=${PARSE_BASE}" > .env && \
    echo "VITE_AUTHENTIK_CLIENT_ID=${AUTHENTIK_CLIENT_ID}" >> .env \
    # and so on...

COPY . .

RUN npm install
RUN npm run build

EXPOSE 3030
CMD ["npx", "vite", "preview", "--host", "--port", "3030"]
Enter fullscreen mode Exit fullscreen mode

You could also copy in a pre-made .env file from your repo or Docker context instead of building it dynamically.

docker-compose.yml — Bind everything together

services:
  liveapi-ui:
    build:
      context: ../client
      dockerfile: dockerfile
      args:
        - PARSE_BASE=${PARSE_BASE}
        - AUTHENTIK_CLIENT_ID=${AUTHENTIK_CLIENT_ID}
        # etc...
    ports:
      - "${LIVEAPI_UI_PORT}:3030"
    env_file:
      - .env
Enter fullscreen mode Exit fullscreen mode

This passes the variables to Docker as ARG, which then get written to .env, which Rollup uses to replace the process.env.* variables.

Result

Your built JavaScript files now have real values like:

const baseURL = "http://localhost:1337/parse";
Enter fullscreen mode Exit fullscreen mode

Not a reference to process.env anymore.

Bonus: Verify Injected Values

`
grep -r 'process' .


Check your built files (
dist, public, or src/ssr/public/js) and search for injected strings like http://localhost:1337/parse`{% endraw %}.

If you still see {% raw %}process.env.*, something in your setup isn’t wired right.

Summary

Part What it does
.env Stores your local dev or production config
@rollup/plugin-replace Injects variables during build
Docker ARG Passes variables from Compose to Docker
RUN echo ... > .env Prepares the .env file inside Docker
docker-compose.yml Manages the build-time arguments cleanly

TL;DR

  • Rollup doesn’t support .env out-of-the-box — use replace() to hard-code values.
  • .env is only used at build time, not runtime.
  • Inject vars using Docker ARG, not ENV, if you want to keep them out of runtime.
  • This pattern works cleanly in Docker + CI/CD pipelines.

LiveAPI helps you get all your backend APIs documented in a few minutes.

With LiveAPI, you can generate interactive API docs that allow users to search and execute endpoints directly from the browser.

LiveAPI Demo

If you're tired of updating Swagger manually or syncing Postman collections, give it a shot.

Top comments (0)

Gen AI apps are built with MongoDB Atlas

Gen AI apps are built with MongoDB Atlas

MongoDB Atlas is the developer-friendly database for building, scaling, and running gen AI & LLM apps—no separate vector DB needed. Enjoy native vector search, 115+ regions, and flexible document modeling. Build AI faster, all in one place.

Start Free