2

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
Robert Moskal
  • 21,737
  • 8
  • 62
  • 86
Jonathan Perry
  • 2,953
  • 2
  • 44
  • 51
  • Is that client or server side code? If it is server side code, what you have should work perfectly. – Robert Moskal May 14 '18 at 13:57
  • It's client side code (React app) that is started with `npm start` command – Jonathan Perry May 14 '18 at 13:58
  • You are going to have to find a way to ship those environment variables to the client. There are many, many ways of doing this, it will have to be done as part of the build process or you could expose the settings via an api. If you are using webpack (most react folks do), you could use one of the solutions described here: https://stackoverflow.com/questions/30030031/passing-environment-dependent-variables-in-webpack – Robert Moskal May 14 '18 at 14:04
  • I gave an answer, but it would help if you posted your docker file. – Robert Moskal May 14 '18 at 15:01
  • I've added the dockerfile as you requested, thanks! @RobertMoskal – Jonathan Perry May 14 '18 at 15:06
  • 1
    In broad stroke, I stand by my answer. Good luck! – Robert Moskal May 14 '18 at 15:11

1 Answers1

3

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
  • 21,737
  • 8
  • 62
  • 86
  • Thanks for the valuable input, I'll try this and report back. Great answer – Jonathan Perry May 14 '18 at 15:27
  • Strange, I'm thinking about writing a little npm package that just dumps some environment variables to a file on the file system that you could run like this: node -r foo/dump dist/index.js – Robert Moskal May 14 '18 at 15:30
  • Let me know if you end up writing one in the next few days :) – Jonathan Perry May 14 '18 at 15:31
  • We eventually injected the variables in the "start" command, but getting the injected variables externally like `REACT_APP_URL=$(APP_URL)` and injecting the `APP_URL` variable in Kubernetes – Jonathan Perry May 15 '18 at 12:50