简体   繁体   中英

Unable to access env variables from dockerfile in React app using webpack DefinePlugin

I am not sure what I am doing wrong. console.log prints undefined . Makefile , config.env , webpack.config.js and package.json are all in root of the project.

Makefile:

docker-run: docker
    docker run -it --env-file config.env -p "80:80" app

config.env

API_KEY=https://test.com

webpack.config.js

plugins: [
        new webpack.DefinePlugin({
            BASE_URL: JSON.stringify('https://myapp.firebaseio.com'),
            'process.env.API_KEY': JSON.stringify(process.env.API_KEY)
        })
    ]

App.js

const App = () => {
    useEffect(() => {
        console.log(process.env.API_KEY);//undefined
        console.log(process.env.BASE_URL);//undefined
        console.log(BASE_URL);//undefined
    }, []);
    return (
        <></>
    );
};

Package.json( npm run docker )

"scripts": {
        "start": "rm -rf dist && webpack-dev-server --mode development --open --hot --port 8090",
        "docker": "rm -rf dist && webpack --mode production && make docker-run"
    },

One mistake I can see here is, you are building the project outside of docker and pushing the artifacts (after build) to docker for serving the webapp.

As per the documentation of DefinePlugin https://webpack.js.org/plugins/define-plugin/

The DefinePlugin allows you to create global constants which can be configured at compile time

Which means, If you have a App.js component like below

import React from 'react';

function App() {
  return (
    <div>
        <p>[process.env.test] = {process.env.test}</p>
        <p>[process.env.NODE_ENV] = {process.env.NODE_ENV}</p>

    </div>
  );
}

export default App;

And webpack config

new webpack.DefinePlugin({"process.env.test": JSON.stringify(process.env.test)})

After running NODE_ENV=production test="A test variable" npm run build (Which internally runs webpack --mode production if bootstrapped with create-react-app)

The component gets compiled to (Only relevant parts of webpack compiled code pasted).

 var i = function() {
        return a.a.createElement(
          "div",
          null,
          a.a.createElement(
            "p",
            null,
            "[process.env.test] = ",
            "A test variable"
          ),
          a.a.createElement(
            "p",
            null,
            "[process.env.NODE_ENV] = ",
            "production"
          )
        );
      }

Here it replaced {process.env.test} and {process.env.NODE_ENV} to A test variable and production at compile time .

Setting any environment variables on server after the build has no effect on the compiled file .

And due to the direct injection of env variables in compiled code, you shouldn't use this to store confidential information (secrets/ private tokens, passwords, IP addresses of internal servers etc).

So, the solution to your original problem might be, to build the artifacts inside the docker container. A sample Docker file follows.

FROM node:10 as react-app
# Create app directory
WORKDIR /usr/src/app
# Set a temporary variable
ENV test="Hello Docker"
COPY . .
RUN npm install
RUN npm run build

FROM nginx:1.12-alpine
COPY --from=react-app /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]  

A sample git repo if you need a reference.

https://github.com/nithinthampi/test-defineplugin .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM