0

We're trying to run a ReactJs in production using Webpack as my build tool. For this purpose we use DefinePlugin to set environment variables.

new webpack.DefinePlugin({
  'process.env.NODE_ENV': JSON.stringify('development'),
  'process.env.API_URL':  JSON.stringify("http://localhost:7852/"),
}),

However for security reasons I don't want to have sensible information in my source code, as example we don't want to put api keys or private urls in webpack configuration. So we are planning to store that values in the environment variables of the production server.

We do the Webpack build in a continuous integration server (Docker Hub). We want to compile in the Docker Servers but we don't want to put the settings in the Docker servers, we only want the settings in the production server. However when we set these values in my production server the result is undefined. Is there a way to set some configuration variables in Webpack to be handle during transpilation (there are several methods) and let the the production server handle the others? Any advice? Thanks in advance.

Community
  • 1
  • 1
  • If this is front-end code you are transpiling/minifying, the URLs and API keys will be exposed through the browser console in any case. – bjudson Sep 30 '16 at 02:57

2 Answers2

1

I've just run into the exact same problem. What I've found is at the time when webpack is run, is where the environment needs to be set in order to be visible by the application. This means that only what's on your CI server (which builds a docker image) will be available to webpack and consequently your app.

Unless your app routes requests through it's server, where the environment is available, to an api server, I couldn't think of a decent solution. What I've chosen to do is set the environment during my TeamCity build and have a separate build for each test and production servers which would create a separate docker image but using the same dockerfile.

Steven E
  • 11
  • 2
0

You can use different webpacks for different environments, and move the sensitive configuration to environment variables. Your app can only see environment variables in a container if they are defined in the Dockerfile using ENV. If you change your app to read all sensitive information from environment variables, and have matching ENV instructions in your Dockerfile, you can specify them at runtime when you start the container.

E.g. in webpack:

new webpack.DefinePlugin({
  'process.env.API_KEY':  JSON.stringify(process.env.API_KEY || 'API_KEY environment variable not defined'),
...

In your Dockerfile add ENV API_KEY and when you run your container, you can pass the environment variables with -e: docker run -e API_KEY=ba3d4db....

Better still, if you have multiple sensitive values, define them in the Dockerfile and at run time pass them in an environment file using --env-file:

> cat Dockerfile
FROM ubuntu
ENV API_KEY \
    ANOTHER_SECRET

> cat env.file
API_KEY=ab3da3bda4d4a4c4c4                                                                                                                   
ANOTHER_SECRET=shhh!         

> docker run --env-file env.file -it  temp bash
root@545d5945ab1b:/# echo $API_KEY
ab3da3bda4d4a4c4c4
root@545d5945ab1b:/# echo $ANOTHER_SECRET
shhh!

Then you can have the same Docker config for every environment, with different contents in env.file, and secure access to the file.

Elton Stoneman
  • 17,906
  • 5
  • 47
  • 44
  • 2
    this would only work if you would be packing the project each time you start a container. If pre-build the DefinePlugin will have already been called and you won't be able to re-define your variables. – rels Jan 11 '18 at 12:45
  • @rels You touched on what I am struggling to find a solution for now. I am trying to build an docker image of a node app that will be built with webpack. I do not want to include environment variables in the image. When webpack runs when building the image it does not have the env variables and injecting them when building a container is too late. Any suggestions? – walkerrandophsmith Oct 06 '18 at 02:16
  • 2
    @walkerrandophsmith The way we did it in the end was by putting an init wrapper on the app, this enables to have an entrypoint that receives settings that are rendered via the node app in the template file. Makes sense? – rels Oct 10 '18 at 15:03
  • Yes thanks for responding. Glad I am not the only one! – walkerrandophsmith Oct 13 '18 at 05:03