I am using docker to build my react application and deploy it in nginx.
I have set an environment variable in docker-compose.yml
version: '2'
services:
nginx:
container_name: ui
environment:
- HOST_IP_ADDRESS= xxx.xxx.xx.xx
build:
context: nginx/
ports:
- "80:80"
After the docker container is created I can see hi
when I echo
the variable inside the container.
However, when I am trying to read it in react using process.env.HOST_IP_ADDRESS
it is logging undefined
.
I read in a blogpost somewhere that the env variables can be only accessed in production environment. Since, I am building the app and deploying it in nginx, I should be able to access it, but for some reason I am not able to read it.
Am I doing something fundamentally wrong here. If so, please let me know a solution. I am not a react expert, I am just managing someone else's code.
UPDATE:
The Dockerfile looks as follows:
FROM node:8 as ui-builder
WORKDIR /home/ui
COPY helloworld .
RUN npm install
RUN npm run build
FROM nginx
COPY --from=ui-builder /home/ui/build /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
The React Component snippet is as follows:
import React, { Component } from 'react';
class HelloWorld extends Component {
render() {
console.log(process.env.HOST_IP_ADDRESS);
return (
<div className="helloContainer">
<h1>Hello, world!</h1>
</div>
);
}
}
export default HelloWorld;
I would like to thank everyone who posted answers and comments.The problem that I was facing was solved using a combination of these answers and some help from other resources.
As suggested by @DavidMaze (in the comments), I started looking into webpack config present in my code. I found out that the webpack was reading all the environment variables declared inside the container.
So I started experimenting with my Dockerfile and docker-compose.yml as I realized that REACT_APP_HOST_IP_ADDRESS
was not being passed as an environment variable when the react was building the code.
The first thing I changed was the Dockerfile. I statically declared the IP inside dockerfile for testingENV REACT_APP_HOST_IP_ADDRESS localhost
.
By doing this I was able to see the value localhost inside the env variables which were read by webpack.
Now I tried passing the ENV Variable from docker-compose to dockerfile as suggested by @Alex in his answer, but it didn't work.
So I referred to https://github.com/docker/compose/issues/5600 and changed the docker-compose.yml and Dockerfile as follows
docker-compose.yml
version: '2'
services:
nginx:
container_name: ui
build:
context: nginx/
args:
REACT_APP_HOST_IP_ADDRESS: ${IP_ADDRESS}
ports:
- "80:80"
where IP_ADDRESS
is exported as an env variable.
Dockerfile
FROM node:8 as ui-builder
WORKDIR /home/ui
COPY helloworld .
RUN npm install
ARG REACT_APP_HOST_IP_ADDRESS
ENV REACT_APP_HOST_IP_ADDRESS $REACT_APP_HOST_IP_ADDRESS
RUN npm run build
FROM nginx
COPY --from=ui-builder /home/ui/build /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
React Component
import React, { Component } from 'react';
class HelloWorld extends Component {
render() {
console.log(process.env.REACT_APP_HOST_IP_ADDRESS);
return (
<div className="helloContainer">
<h1>Hello, world!</h1>
</div>
);
}
}
export default HelloWorld;
This configuration makes available the variables passed via ARG in docker-compose to Dockerfile during the image build process and hence the variables can be in turn declared as env variables which React can use during build process provided the webpack reads the env variables.
The webpack will be able to read the env variables using DefinePlugin https://webpack.js.org/plugins/define-plugin/.
Make sure you prefix your variables with REACT_APP_
(as seen here), otherwise it won't be picked up by React.
Env variables should start with REACT_APP_ otherwise NODE_ENV variables are a bit confused and your environment variable will not work:
environment:
- REACT_APP_DEBUG=TRUE
Otherwise, docker-compose.yml
is not valid and you will see an error message:
services.client.environment contains an invalid type, it should be an object, or an array
Here is a working sample:
docker-compose.yml
version: "3.3"
services:
client:
container_name: client
environment:
- REACT_APP_DEBUG=TRUE
build:
dockerfile: Dockerfile
context: ./web/client
Dockerfile
FROM node:6.0.0
# Set env variable
ARG REACT_APP_DEBUG
ENV REACT_APP_DEBUG=$REACT_APP_DEBUG
# that will be empty
RUN echo "DEBUG": $REACT_APP_DEBUG
Run:
->docker-compose run client node
->process.env.REACT_APP_DEBUG
'TRUE'
You should check next moments
I. You env variables have prefix REACT_APP_
II. In docker file you have ARG and ENV commands like
ARG REACT_APP_DEBUG
ENV REACT_APP_DEBUG=$REACT_APP_DEBUG
III. you pass your arg as build arg in docker-compose.yml it looks like
services:
my-app:
build:
args:
REACT_APP_DEBUG=True
or in docker build it looks like
docker build -t my_app:dev --build-arg REACT_APP_DEBUG=True .
I checked how it's done in API Platform, config just defines consts based on env ('.env' file):
export const API_HOST = process.env.REACT_APP_API_ENTRYPOINT;
export const API_PATH = '/';
Importing this you have one value (API_HOST) while process.env.HOST_IP_ADDRESS
refers to deep object structure unavailable at runtime.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With