Aarni Joensuu
Aarni Joensuu

Reputation: 741

Creating React application for production with Docker build?

I am creating a React application using docker build with the following Dockerfile:

# build env
FROM node:13.12.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm ci
RUN npm install react-scripts -g
RUN npm install --save @fortawesome/fontawesome-free
RUN apk add nano
RUN apk add vim
COPY . ./
RUN npm run build

# production env
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

I believe the Dockerfile is not of extreme importance here however. In my source code there is a master configuration file, which I want to leave out of the docker image to be able to deploy my React App easily. This causes a compilation error during the Dockerfile command RUN npm run build, since the compilator does not find a file that is referenced by another file. For development versions this was not an issue, since npm start is not that sensitive.

I would add the configuration file as a docker volume in the final application, so the code would be able to find it without problems. I am just wondering how to approach a situation like this, since it has not come up earlier on my path?

Also feel free to comment on or optimize my Dockerfile, as I am unsure of e.g. whether Nginx is the way to go in these production builds for website front-end applications.

Upvotes: 2

Views: 14156

Answers (2)

Seeker
Seeker

Reputation: 209

Here is a sample of my react docker file. May be you can use this if you want to optimize.

PS: i am running it from kubernetes.

# #############################   Stage 0, Build the app   #####################
# pull official base image
FROM node:13.12.0-alpine as build-stage
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# install app dependencies
COPY package*.json ./
#RUN npm install
RUN npm install

# add app
COPY . ./

#build for production
RUN npm run-script build

# #### Stage 1, push the compressed  built app into nginx ####
FROM nginx:1.17

COPY --from=build-stage /app/build/ /usr/share/nginx/html
  

Upvotes: 0

AKX
AKX

Reputation: 169338

If your app currently requires the configuration file, it's akin to "hard-coding" the values into it at build time, as you've noticed. If you do need to be able to dynamically swap in another configuration file at runtime, you would need to use e.g. fetch() to load it, not bundle it (as require does).

If configuring things at build-time is fine, then I'd also suggest looking at CRA custom environment variables; you could then inject the suitable values as environment variables at build time.

Beyond that, if you're looking for critique for your Dockerfile, from one Aarni to another:

  • Your package.json is broken if you need to do anything beyond npm ci or yarn during a build to install stuff. react-scripts should be a dev dependency and Font Awesome should be a regular dependency.
  • You don't need nano and vim in the temporary container, and even if you did, it'd be better to apk add them in a single step.
  • You shouldn't need to modify the PATH in the build container.
  • Using Nginx is absolutely fine.
# build env
FROM node:13.12.0-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . ./
RUN npm run build

# production env
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Upvotes: 8

Related Questions