irregular
irregular

Reputation: 1587

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

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.

Upvotes: 13

Views: 19311

Answers (3)

patrick
patrick

Reputation: 10273

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.

Upvotes: 1

LucasBordeau
LucasBordeau

Reputation: 1568

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 "$@" 
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

Upvotes: 7

Mike S.
Mike S.

Reputation: 4879

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.

Upvotes: 9

Related Questions