Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 516
irregular Avatar asked Oct 24 '17 01:10

irregular


2 Answers

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.

like image 85
Mike S. Avatar answered Sep 24 '22 19:09

Mike S.


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
like image 39
LucasBordeau Avatar answered Sep 20 '22 19:09

LucasBordeau