Blogpost for this stackoverflow answer: https://stackoverflow.com/a/74701083/1485527
Get code here
Create example app
npx create-react-app read-env-example --template typescript
Navigate to fresh app
cd read-env-example
Create Dockerfile
mkdir -p docker/build
docker/build/Dockerfile
# build environment
FROM node:19-alpine3.15 as builder
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm ci
RUN npm install react-scripts@5.0.1 -g
COPY . ./
RUN PUBLIC_URL="." npm run build
# production environment
FROM nginx:stable-alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
COPY docker/build/docker-entrypoint.sh /
RUN chmod +x docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
Create docker-entrypoint.sh
This script will be executed at container start.
It generates the config.js
file containing all environment variables starting with ‘MYAPP’ under window.extended
.
docker/build/docker-entrypoint.sh
#!/bin/sh -eu
function generateConfigJs(){
echo "/*<![CDATA[*/";
echo "window.extended = window.extended || {};";
for i in `env | grep '^MYAPP'`
do
key=$(echo "$i" | cut -d"=" -f1);
val=$(echo "$i" | cut -d"=" -f2);
echo "window.extended.${key}='${val}' ;";
done
echo "/*]]>*/";
}
generateConfigJs > /usr/share/nginx/html/config.js
nginx -g "daemon off;"
Create docker-compose.yml
mkdir docker/run
docker/run/docker-compose.yml
version: "3.2"
services:
read-env-example:
image: read-env-example:0.1.0
ports:
- 80:80
env_file:
- myapp.env
Create runtime config for your app
docker/run/myapp.env
MYAPP_API_ENDPOINT='http://elasticsearch:9200'
Create config.js <– this is where .env will be injected.
public/config.js
/*<![CDATA[*/
window.extended = window.extended || {};
window.extended.MYAPP_API_ENDPOINT='http://localhost:9200';
/*]]>*/
Note: This file will be completely overwritten by the docker-entrypoint.sh
. For development purposes you can set it to any value that is appropriate, e.g. when used together with npm start
.
Include config.js in index.html
public/index.html
<head>
...
<script type="text/javascript" src="%PUBLIC_URL%/config.js" ></script>
...
</head>
<body>
Make use of your environment variable
src/App.tsx
declare global {
interface Window { extended: any; }
}
function App() {
return (
<div className="App">
<header className="App-header">
You have configured {window.extended.MYAPP_API_ENDPOINT}
</header>
</div>
);
}
Build
npm install
Create docker image
docker build -f docker/build/Dockerfile -t read-env-example:0.1.0 .
Run container
docker-compose -f ./docker/run/docker-compose.yml up
Navigate to your app
Open http://localhost in your browser.
You will see the content of MYAPP_API_ENDPOINT
like provided in your docker/run/myapp.env
.
Further usage
You can provide additional variables starting with MYAPP
. The docker-entrypoint.sh
script will search for all variables starting with MYAPP
and make them available through the windows
object.