Running pods have some environment variables defined inside, for example:
/ # printenv
REACT_APP_ENV_VARIABLE=Variable from Kube!
REDIS_SERVICE_PORT=6379
KUBERNETES_SERVICE_PORT=443
KUBERNETES_PORT=tcp://10.38.0.1:443
REDIS_PORT=tcp://10.38.61.225:6379
REDIS_PORT_6379_TCP_ADDR=10.38.61.225
HOSTNAME=playground-pod
PLAYGROUND_SERVICE_SERVICE_HOST=10.38.0.53
REDIS_PORT_6379_TCP=tcp://10.38.61.225:6379
PLAYGROUND_SERVICE_SERVICE_PORT=80
PLAYGROUND_SERVICE_PORT=tcp://10.38.0.53:80
PLAYGROUND_SERVICE_PORT_80_TCP_ADDR=10.38.0.53
KUBERNETES_PORT_443_TCP_PROTO=tcp
PLAYGROUND_SERVICE_PORT_80_TCP_PORT=80
PLAYGROUND_SERVICE_PORT_80_TCP_PROTO=tcp
REACT_APP_ENV_VARIABLE_TWO=192.168.1.12
PLAYGROUND_SERVICE_PORT_80_TCP=tcp://10.38.0.53:80
How should I configure a React app like this one:
function App() {
return (
<div className="App">
<header className="App-header">
<p>
<code>ENV. VARIABLE: </code> {x.REACT_APP_ENV_VARIABLE}
</p>
</header>
</div>
);
}
export default App;
to read and inject some of the variables present in the pod?
The main reason I want to know it, is dynamic update of e.g. backend or Redis URLs – they might change when the app is restarted, rescheduled, etc.
My first approach was using a config.json
file imported to the app, but this way I can’t import dynamic values generated by running pods.
3
Answers
As @Harsh Manvar suggested (thanks a lot!), the
react-dotenv
library can be used, but just adding it to the project is not enough.Firstly, you have to follow all steps described in react-dotenv documentation (adding
.env
file to your project, editingpackage.json
file).In my case,
.env
file looked like this:These are just placeholders for real values that will be added during runtime.
Having the
.env
file ready,npm
scripts prepended withreact-dotenv
command, and the variables whitelisted (as described in the library documentation), you can build your app image.When the image is ready, add it to the
kubernetes
pod config file and replace your variables' placeholders with real values, like this:What happened up there, was replacing placeholder values with actual values:
$BACKEND_SERVICE_HOST
is an environment variable that exists in the pod and can be read from the running container,$REACT_APP_DEPLOY_SETUP
is a regular string defined by user,$REACT_APP_PORT
is an integer value (it has to be in quotes, like strings!).And the replacing happened with
sed
command (or rather:sh -c "sed -i ..."
). All of the commands are chained, so don't forget about semicolons at the end of each argument.All of the replacements were made in
/usr/share/nginx/html/env.js
file, which is created byreact-dotenv
library in project root. The actual location depends on where you mounted your build image (it's defined inDockerfile
).Lastly,
nginx
command is called, since this is the final command invoked in image'sDockerfile
. Without this explicit call, the command from theDockerfile
would be overwritten with the commands related to the pod container and, in this case,nginx
wouldn't start your app.After the pod is started, you can check whether the variables are present in the container:
But it doesn't mean they were read by your app during runtime. To see if they were changed to the values from the pod definition, you can either
exec
running pod container and preview theenv.js
file or add some console logging in the app code.You can use the library dot-env
while in deployment you can pass secret from secret and configmap
Above scenario fit well with your requirement, instead of using the
config.json
.You can pass multiple values to deployment using configmap and secrets.
I don’t have enough reputation to comment under someone else’s answer yet, but just to add to @AbreQueVoy’s answer:
I had trouble with one of my variables: It was a URL.
The first character after the s (/) is our separator: Thus SED freaked out when getting a URL. I simply replaced the / and changed the separator to a , like so:
I did find this tutorial useful for learning a bit about SED.