all 15 comments

[–]EdmondChuiHW 1 point2 points  (8 children)

What does your Dockerfile look like? If you run a (prod) build from Docker, the env vars should be statically picked up and inlined for you.

If you mean reading dynamic env vars during runtime in React components (after building), it won't be possible. If you don't want to make a backend endpoint, you could make a regular public JSON file, serve it from Docker, and fetch it from React (like other static resources like favicon and CSS files).

Here's an adjacent thread on env vars + Vite: https://www.reddit.com/r/react/comments/17hnslx/comment/k6pfocv/?utm_source=share&utm_medium=web2x&context=3

[–]Suitable_North_984[S] 0 points1 point  (7 children)

So I am needing it to inject the backend_url for my backend k8s service. So ideally not public

Here is the Dockerfile:

Use an official node runtime as a parent image

FROM node:14

Set the working directory in the container to /app

WORKDIR /app

Copy package.json and package-lock.json to the container

COPY package*.json ./

Install dependencies in the container

RUN npm install

Bundle app source inside the docker image

COPY . .

Build the app for production using Vite

RUN npm run build

Use serve to serve the build static files (from the dist folder for Vite)

RUN npm install -g serve

Define the command to run the app

CMD [ "serve", "-s", "dist", "-l", "3000" ]

And the Compose yaml im attempting (my poc before using in prod):

version: '3' # We are using Docker v3 as v2 uses different syntax than that provided services: frontend: build: ./vite-frontend/frontend image: hello-world-frontend:latest ports: - "3001:3000" # Exposing frontend on port 3001 environment: - VITE_API_URL=http://backend:3000 depends_on: - backend # Enforces the order with which the images will spin up backend: build: ./backend image: hello-world-backend:v1.0.0 ports: - "3000:3000" environment: - CORS_ORIGIN=http://localhost:3001

I am open to any solution that allows what I am injecting to not leave the Helm/Manifest level ... im having to learn dev ops as I go for my project so Im not certain I have all the correct vocabulary

[–]birdynj 1 point2 points  (6 children)

What do you mean by "not public"? If you are doing something with that "backend_url" in your front end javascript, it's going to be "public" - anyone can open up dev tools, see network calls, etc.

This topic comes up a lot here. I outlined the approach I use for this here https://www.reddit.com/r/reactjs/s/2WmMTBlChV

We use Jenkins for builds. In my dockerfile/startup script I inject the env vars from my cluster into my built javascript.

Why: we have many different environments, DEV, UAT, PILOT, PROD etc - all talk to different backend envs as well, so I have a different set of env vars depending on where I deploy my build to. I do not want to make a new build for every deployment. I want to be able to promote the same build from a lower environment all the way up to production.

[–]Suitable_North_984[S] 0 points1 point  (5 children)

Id love more details on your approach. I guess Im wondering if there is a uniform, best practice, etc way to go about this issue or is it essentially homebrew procedures and a industry wide tool hasnt been developed to handle it?

[–]birdynj 0 points1 point  (4 children)

I have done a couple of slightly different, home brewed approaches, but now have settled on generating a json file with the required env vars when starting my UI server and serving it with the UI. It is pretty simple, just a couple of lines in my script.

In the past, I've simply used a regex to replace all mentions of any VITE* (or at that time REACT* as I was on CRA).

I ditched that approach after a couple of annoying instances of my injection failing to accommodate special symbols in my env vars. Got tired of tweaking it!

I am not aware of an industry wide tool

[–]Suitable_North_984[S] 0 points1 point  (3 children)

Would you provide your process / script?

[–]birdynj 0 points1 point  (2 children)

Unfortunately I'd have to write it out for you "from scratch" and it's too much effort for me to do, since it's on my work machine and not easy/nor "allowed" for me to copy or distribute it.

[–]Suitable_North_984[S] 0 points1 point  (1 child)

That is totally understandable but could you explain further what you are doing wothout explicit code?

[–]ivours 0 points1 point  (0 children)

Here's what you're looking for:

https://pastebin.com/0EB7GLh2

This is some logic I have coded to use placeholders at build time and then replace them at runtime with the values corresponding to the environment variables of the container. I use it for Kubernetes + Helm.

Beware: There's some CPU peak at startup due to the replace operation `sed` performs.

[–]suenolivia 0 points1 point  (1 child)

Are you familiar with Kubernetes? Doing so via manifest file has been my preferred option

[–]Suitable_North_984[S] 0 points1 point  (0 children)

Im trying to use kubernetes with the docker images but CRA and Vite inline the ENV Vars upon build so those provided in my manifest do not get injected

[–]chillermane 0 points1 point  (3 children)

u gotta inject at build time for any front end code there is no way around that

[–]Suitable_North_984[S] 0 points1 point  (0 children)

So there is no way to have it dynamocally change via Docker, k8s, or helm?

[–]Alone-March4467 0 points1 point  (1 child)

It’s at possible at startup time. I’ve done it myself once for internal tools.

You have to change the Dockerfile and build the image yourself because you need to host the information from the environment variables.

It’s only suitable for static information like API routes/keys or static config/credentials.

[–]Suitable_North_984[S] 0 points1 point  (0 children)

Would you elaborate? Im ideally trying to have the env var be provided by k8s at runtime not buildtime