Louay GOURRIDA
Louay GOURRIDA

Reputation: 202

docker build doesnt take changes .env in consideration

i have been trying to make a CI-CD pipline for a project i have 2 backends one is deployed on http://141.9*.*****:8800/ and the other one is depolyed on vps-a******.*******:8800(some of the server links are hidden for security reasons)

anyway in .env i have this REACT_APP_SERVER_URL='http://vps-a******.*******:8800' just this one line

and this is what i have in my dockefile

#you have to build the app manually first
# production environment

# pull official base image
FROM node:16-alpine AS node-build

# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH


# install app dependencies
COPY package.json ./
COPY package-lock.json ./
RUN npm i --force
#RUN npm install [email protected] -g --silent

# add app
COPY . ./

RUN npm run build --force

# production environment
FROM nginx:stable-alpine
COPY /build /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 6100
CMD ["nginx", "-g", "daemon off;"]

it doenst matter what i make in .env like change it to localhost or 141.****it keeps always connecting to vps-a******.*******:8800

well if i build the app manually and run npm run build in terminal then build the image it connects to whatever link i put in .env

i cant keep doing that(building the app locally before building the image) because im working on a ci-cd pipline i want it to be done via docker file so how can i take .env in considartion while building the app using docker file ?

Upvotes: 6

Views: 1697

Answers (2)

jccampanero
jccampanero

Reputation: 53411

Please, be aware that I normally don't work with React, excuse me if I say something incorrect.

You mentioned react-scripts and the way your properties look like makes me think you are trying providing custom environment variables to your React application.

If you created your application with the create-react-app generator, as described in the documentation, for this feature work properly you need to use an appropriate version of react-scripts and to create a .env file in your application root directory, and define in that file the appropriate variables. React will recognize all the environment variables starting with the REACT_APP_ prefix. Exactly as you did.

These variables will be defined for on process.env. For example, in your use case, the environment variable REACT_APP_SERVER_URL will be exposed in your JS as process.env.REACT_APP_SERVER_URL.

Be aware that create-react-app provides a simplification of the functionally exposed by dotenv. Please, consider read this related SO question for a more general use case explanation.

As indicated in the aforementioned documentation, is important to understand that generally:

The environment variables are embedded during the build time.

i.e, it will replace the placeholders for your environments variables when compiling the application, when it generates your HTML, JS and CSS resources.

You are using a docker multistage build to first, create your application bundle, and then deploy it to nginx.

I am assuming your are using a stardard create-react-app directory structure:

my-app/
  README.md
  .env
  node_modules/
  package.json
  public/
    index.html
    favicon.ico
  src/
    App.css
    App.js
    App.test.js
    index.css
    index.js
    logo.svg

Note I included the required .env file.

Your Dockerfile looks fine to me, although I tried to provide a simplified version, something like this:

# pull official base image
FROM node:16-alpine AS node-build

# set working directory
WORKDIR /app

# install app dependencies, I normally do not use package-lock.json here
COPY package.json ./
# just, install the required stuff
RUN npm install

# now, build the app
# in this process is where the placeholders for your environment variables
# should be replaced by the information you defined inn your .env file
COPY ./src ./src
COPY ./public ./public
# explicitly copy your .env file
COPY .env ./
# perform the actual build. this will generate a /build folder
RUN npm run build

# production environment
FROM nginx:stable-alpine
# document where your app listen
EXPOSE 6100
# copy your nginx site configuration
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
# I always prefer to clean the nginx default web directory before 
# copying the SPA output
RUN rm -rf /usr/share/nginx/html/*
# copy the contents of your /build folder from your node-build image
# to the nginx web root dir. note in the code snippet you provided in your
# question you are not doing this
COPY --from=node-build /app/build/ /usr/share/nginx/html
# instruct your server to run in the foreground
CMD ["nginx", "-g", "daemon off;"]

Upvotes: 2

Shachar297
Shachar297

Reputation: 842

So I guess you have a .env file which your backend requires it in the code.

Any way, you could use the ENV method. This will write your variable to the container on it's runtime.

#you have to build the app manually first
# production environment

# pull official base image
FROM node:16-alpine AS node-build

ENV REACT_APP_SERVER_URL='http://vps-a******.*******:8800'

# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH


# install app dependencies
COPY package.json ./
COPY package-lock.json ./
RUN npm i --force
#RUN npm install [email protected] -g --silent

# add app
COPY . ./

RUN npm run build --force

# production environment
FROM nginx:stable-alpine
COPY /build /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 6100
CMD ["nginx", "-g", "daemon off;"]

Upvotes: 1

Related Questions