DEV Community

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

Posted on • Edited on

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

Hello, I'm Maneshwar. I'm building git-lrc, an AI code reviewer that runs on every commit. It is free, unlimited, and source-available on Github. Star Us to help devs discover the project. Do give it a try and share your feedback for improving the product.

Hi there! Right now, I’m building , a first-of-its-kind tool that helps you automatically index API endpoints across all your repositories. 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, notruntime.
  • 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.

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

git-lrc
*AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.*

Any feedback or contributors are welcome! It's online, source-available, and ready for anyone to use.

⭐ Star it on GitHub:

GitHub logo HexmosTech / git-lrc

Free, Unlimited AI Code Reviews That Run on Commit




AI agents write code fast. They also silently remove logic, change behavior, and introduce bugs -- without telling you. You often find out in production.

git-lrc fixes this. It hooks into git commit and reviews every diff before it lands. 60-second setup. Completely free.

See It In Action

See git-lrc catch serious security issues such as leaked credentials, expensive cloud operations, and sensitive material in log statements

git-lrc-intro-60s.mp4

Why

  • 🤖 AI agents silently break things. Code removed. Logic changed. Edge cases gone. You won't notice until production.
  • 🔍 Catch it before it ships. AI-powered inline comments show you exactly what changed and what looks wrong.
  • 🔁 Build a

Top comments (0)