Create-React-App not reading environment variable from docker-compose.yml

10,793

Solution 1

I noticed a lot of people struggle with this, and particularly how to pass ENV vars instead of conditional scripting in Dockerfile, so I provided a simplified Github repo tutorial:

- https://github.com/mikesparr/tutorial-react-docker

Background via a public article on LinkedIn articles if you care to read:

- https://www.linkedin.com/pulse/dockerizing-your-react-app-mike-sparr/


In short, you need your Dockerfile CMD to run a script that performs the build and the server start steps so the app can use the runtime container configs.

Also, you need to prefix your ENV vars with REACT_APP_<yourvarname> and in your app, reference them using process.env.REACT_APP_SOMEVAR.

Solution 2

Create-react-app prefers to have a .env file in order to embed your env vars into the build.

Obviously it's not a good practice to version control a .env file, the create-react-app official documentation go against the 12-factor-app philosophy.

So let's use a clean solution ! The most simple way is to create a .env file on the fly into the Dockerfile build environment :

For this create a simple script create-env-file.sh :

touch .env
for envvar in "[email protected]" 
do
   echo "$envvar" >> .env
done

It will copy every args you pass it to a new .env file

Then call it before RUN npm run build in your Dockerfile :

FROM node:14-alpine
WORKDIR /app
COPY src/ ./src/
COPY public/ ./public/
COPY pack*.json ./
COPY tsconfig.json .
COPY create-env-file.sh ./create-env-file.sh
RUN npm i
# Add as many arguments as you want to pass environment variables 
#   and use an ARG command for each one, so Dockerfile context will grab it from --build-arg
ARG REACT_APP_ENDPOINT
RUN sh create-env-file.sh REACT_APP_ENDPOINT=$REACT_APP_ENDPOINT
# If you want to debug the .env file, uncomment the following line
# CMD ["cat", ".env"]
RUN npm run build
RUN npm i -g serve
EXPOSE 5000
CMD ["serve", "-s", "build"]

Then use --build-arg to pass your env vars to the docker build command :

docker build --build-arg REACT_APP_ENDPOINT=http://api.com -t front-server .

You have to reference each passed build arg with an ARG command because docker build consider build args as arguments and NOT environment variables. See here

So your docker-compose.yml would look like this :

version: "3"
services:
  web:
    build:
      context: .
      args:
        REACT_APP_ENDPOINT=http://api.com
    image: user1/webapp:latest
    volumes:
      - ./local-db:/go/src/webapp/local-db
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "8080:8080"
    networks:
      - webnet
networks:
  webnet:

Use --build with docker-compose up :

docker-compose up --build

Solution 3

Create React App has support for .env files, which means you can put permanent environment variables in one of these files to make it available to the app.

You are putting yours in your docker-compose.yml.

There is a solution for handling this found here: https://github.com/facebookincubator/create-react-app/issues/982#issuecomment-273032553.

Specifically, step #3.

Share:
10,793

Related videos on Youtube

irregular
Author by

irregular

Updated on October 29, 2022

Comments

  • irregular
    irregular 10 days
    version: "3"
    services:
      web:
        # replace username/repo:tag with your name and image details
        image: user1/webapp:latest
        volumes:
          - ./local-db:/go/src/webapp/local-db
        environment:
          - REACT_APP_ENDPOINT=http://api.com
        deploy:
          replicas: 5
          resources:
            limits:
              cpus: "0.1"
              memory: 50M
          restart_policy:
            condition: on-failure
        ports:
          - "8080:8080"
        networks:
          - webnet
    networks:
      webnet:
    

    webapp is server that serves a create-react-app but when I run

    console.log("process.env.REACT_APP_ENDPOINT")
    console.log(process.env.REACT_APP_ENDPOINT)
    

    according to https://daveceddia.com/multiple-environments-with-react/ I should be able to access the environment variables. I run the docker-compose using

    docker swarm init 
    docker stack deploy -c ~/webapp/docker-compose.yml webapp 
    

    The console log prints undefined but if I run the server serving create-react-app on my local machine without docker, the frontend properly prints the environment variable.

  • zipzit
    zipzit almost 2 years
    From what I can see, this answer does not specifically answer the original question, how to read an environmental variable for a create-react-app docker container. Instead it shows how to build a single container from a known directory on a single computer. Hint, when we deploy a system, there are often multiple containers in a single location (frontend, backend, db, management tools, etc....) For anyone with multiple containers, this answer is nice, but doesn't help. And when we do multiple containers, we build from a git repo. .env files won't work.
  • zipzit
    zipzit almost 2 years
    Bootstrapped React apps (using create-react-app) strip most environment variables with the exception of NODE_ENV and any variables that are prefixed with REACT_APP_<your var>. Yowza. I didn't realize this. Changed variable names = success. Many thx.
  • Luca Perico
    Luca Perico almost 2 years
    It works only if you use "npm run" command, but if you have a Dockerfile which does the npm run build command, the .env variables are left out.
  • Karanveer Singh
    Karanveer Singh 12 months
    This is brilliant. Thanks!!!
  • frab 9 months
    Using this approach, is it possible to build the image and then set the args in docker-compose later?