Injecting variables to config.js with Kubernetes

5/14/2018

I have a ReactJS application and I'm deploying it using Kubernetes.

I'm trying to wrap my head around how to inject environment variables into my config.js file from within the Kubernetes deployment file.

I currently have these: config.js file:

export const CLIENT_API_ENDPOINT = { 
    default:process.env.URL_TO_SERVICE,
};

and here's my Kubernetes deployment variables:

"spec": {
  "containers": [
    {
      "name": "container_name",
      "image": "image_name",
      "env": [
        {
          "name": "URL_TO_SERVICE",
          "value": "https://www.myurl.com"
        }
      ]

Kinda clueless of why I can't see the environment variable in my config.js file. Any help would be highly appreciated.

Here's my dockerfile:

# Dockerfile (tag: v3)
FROM node:9.3.0
RUN npm install webpack -g
WORKDIR /tmp
COPY package.json /tmp/
RUN npm config set registry http://registry.npmjs.org/ && npm install
WORKDIR /usr/src/app
COPY . /usr/src/app/
RUN cp -a /tmp/node_modules /usr/src/app/
#RUN webpack
ENV NODE_ENV=production
ENV PORT=4000
#CMD [ "/usr/local/bin/node", "./index.js" ]
ENTRYPOINT npm start
EXPOSE 4000
-- Jonathan Perry
kubernetes
node.js
reactjs
webpack

1 Answer

5/14/2018

The kubernetes environment variables are available in your container. So you would think the task here is a version of getting server side configuration variables shipped to your client side code.

But, If your react application is running in a container, you are most likely running your javascript build pipeline when you build the docker image. Something like this:

RUN npm run build

# Run app using nodemon
CMD [ "npm", "start" ]

When docker is building your container, the environment variables injected by kubernetes aren't yet yet available. They won't exist until you run the built container on a cluster.

One solution, and this is maybe your shortest path, is to stop building your client side code in the docker file and combine the build and run steps in npm start command . Something like this if you are using webpack:

"start": "webpack -p --progress --config webpack.production.config.js && node index.js"

If you go this route, then you can use any of the well documented techniques for shipping server side environment variables to your client during the build step : Passing environment-dependent variables in webpack. There are similar techniques and tools for all other javascript build tools.

Two: If you are running node, you can continue building your client app in the container, but have the node app write a config.js to the file system on the startup of the node application.

You could do even more complicated things like exposing your config via an api (a variation on the second approach), but this seems like throwing good money after bad.

I wonder if there isn't an easier way. If you have a purely client side app, why not just deploy it as a static site to, say, an amazon or gcloud bucket, firebase, or netlify? This way you just run the build process and deploy to the correct environment. no container needed.

-- Robert Moskal
Source: StackOverflow