11

I have a react front-end application that is being built via webpack and containerised using docker.

Goal: Is to be able to define environment variables in docker and be able to access the environment variables in my reactjs application.

docker-compose.yml

version: '3'

services:
  portal:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=production
      - PORT=8080
      - API_URL=http://test.com
    ports:
      - "8080:8080"

For example i want to access this api_url variable in my reactjs app

webpack.prod.js

const path = require('path');
const nodeExternals = require('webpack-node-externals');
const WebpackShellPlugin = require('webpack-shell-plugin');
const CopyWebpackPlugin = require("copy-webpack-plugin");
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const webpack = require('webpack');
const dotenv = require('dotenv');

console.log(process.env);

module.exports = [{
    entry: {
        app1: ["./src/public/app1/index.tsx"],

    },
    mode: NODE_ENV,
    watch: NODE_ENV === 'development',
    output: {

        filename: "[name]/bundle.js",
        path: path.resolve(__dirname, 'build/public/'),
    },

    // Enable sourcemaps for debugging webpack's output.
    devtool: "source-map",

    resolve: {
        // Add '.ts' and '.tsx' as resolvable extensions.
        extensions: [".ts", ".tsx", ".js", ".json", ".css", ".scss"]
    },

    module: {
        rules: [
            { test: /\.tsx?$/, loader: "awesome-typescript-loader" },


            // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
            { enforce: "pre", test: /\.js$/, loader: "source-map-loader" },

            { test: /\.scss$/, use: [ 
                { loader: "style-loader" },  // to inject the result into the DOM as a style block
                { loader: "css-loader", options: { modules: true } },  // to convert the resulting CSS to Javascript to be bundled (modules:true to rename CSS classes in output to cryptic identifiers, except if wrapped in a :global(...) pseudo class)
                { loader: "sass-loader" },  // to convert SASS to CSS
            ] }, 
        ]
    },
    "plugins": [
        // new CleanWebpackPlugin(),
        new webpack.DefinePlugin({
            'process.env.API_URL': JSON.stringify(process.env.API_URL)
        }),

        new CopyWebpackPlugin([
            {
                from: "src/public/app1/index.html",
                to: "app1"
            },
        ]),
    ],



    // When importing a module whose path matches one of the following, just
    // assume a corresponding global variable exists and use that instead.
    // This is important because it allows us to avoid bundling all of our
    // dependencies, which allows browsers to cache those libraries between builds.
    externals: {
        // "react": "React",
        // "react-dom": "ReactDOM"
    }
}]

You can see im trying to set the environment variables in webpack with the following plugin

   new webpack.DefinePlugin({
                'process.env.API_URL': JSON.stringify(process.env.API_URL)
            }),

Problem: You can see i have console logged process.env in my webpack config BUT none of the environment variables i set in the docker are shown.

Context:

DockerFile

FROM node:10.16.0-alpine
# Bundle APP files
WORKDIR /app
COPY ./ /app/
# Install app dependencies
ENV NPM_CONFIG_LOGLEVEL warn
RUN npm ci
RUN npm run build

npm

"build": "webpack --config webpack.prod.js",
3
  • Have you followed all the steps mentioned here github.com/facebook/create-react-app/issues/… Commented Jun 19, 2019 at 8:31
  • Im not using create-react-app Commented Jun 19, 2019 at 8:31
  • But as you can see im doing everything they are. Commented Jun 19, 2019 at 8:33

1 Answer 1

6

The environment variables in your docker-compose.yml file will only be made available when your container starts.

If you want them available during the build as well, then you can use build args:

version: '3'

services:
  portal:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        - NODE_ENV=production
        - PORT=8080
        - API_URL=http://test.com
    ports:
      - "8080:8080"

Then, in your Dockerfile, declare the build args using the ARG command, and then declare the ENV variables, setting them to the value of the build args:

FROM node:10.16.0-alpine

# Build args
ARG NODE_ENV
ARG PORT
ARG API_URL

# Environment vars
ENV NODE_ENV=$NODE_ENV
ENV PORT=$PORT
ENV API_URL=$API_URL

# Bundle APP files
WORKDIR /app
COPY ./ /app/

# Install app dependencies
ENV NPM_CONFIG_LOGLEVEL warn
RUN npm ci
RUN npm run build

I hope this helps.

Sign up to request clarification or add additional context in comments.

3 Comments

Can you give an explanation as to why you think args would work and not environment?
thank you this worked, but i;m not a fan of having to define all these args and envs in my dockerfile especially if you have a lot of them.
whats your opinon would you do it this way or using a .env file and .env.production file?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.