Reputation: 1587
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
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
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
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