Dockerizing react for production not working - reactjs

I have created a Dockerfile and Docker-compose.yml for containerzing my create-react-app to production. My problem of understanding is how should I create the production build if the scripts that are needed to run the command are dev-dependencies?
Also I can`t find anything on deployment docs.
> [builder 7/7] RUN yarn build:
#13 0.507 yarn run v1.22.19
#13 0.556 $ react-scripts build
#13 0.579 /bin/sh: react-scripts: not found
#13 0.590 error Command failed with exit code 127.
#13 0.590 info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
------
executor failed running [/bin/sh -c yarn build]: exit code: 127
ERROR: Service 'app' failed to build : Build failed
`docker-compose` process finished with exit code 1
package.json
{
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-i18next": "^11.17.2",
"react-router-dom": "^6.3.0",
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build", <--- THIS WILL BE USED FOR PRODUCTION
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"devDependencies": {
"react-scripts": "5.0.1", <--- THIS WILL NOT BE INSTALLED WITH --production FLAG
"tailwindcss": "^3.0.24",
"typescript": "^4.6.3"
}
}
Dockerfile
FROM node:18-alpine AS builder
ENV NODE_ENV production
# Add a work directory
WORKDIR /app
# Cache and Install dependencies
COPY package.json .
COPY yarn.lock .
RUN yarn install --production <---- THIS DOES NOT INSTALL DEV DEPENENCIES
# Copy app files
COPY . .
# Build the app
RUN yarn build <---- THIS CAUSES THE CRASHING
# ---------------------------------------------------
# Bundle static assets with nginx
FROM nginx:1.23.1-alpine AS production
ENV NODE_ENV production
# Copy built assets from builder
COPY --from=builder /app/build /usr/share/nginx/html
# Add your nginx.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Expose port
EXPOSE 80
# Start nginx
CMD ["nginx", "-g", "daemon off;"]
docker-compose.yml
version: "3.8"
services:
app:
container_name: my_app
build:
context: .
target: production
dockerfile: Dockerfile

In the final image stage, you're only COPY --from=builder the /app/build directory but not any of the node_modules tree. It doesn't matter in the initial stage if you have development or production dependencies, since they're not going to be in the final image.
Since you do need the devDependencies at this point, I'd remove the yarn install --production option. If it makes a difference to your build environment you can set NODE_ENV=production after you install the dependencies.
RUN yarn install # not --production
COPY . .
# ENV NODE_ENV=production
RUN yarn build

Related

Can't build react app in docker in production environment

I'm trying to build a react docker image with NODE_ENV set to production, but keep getting this error:
#0 11.74 > webpack --config webpack-prod.config.ts
#0 11.74
#0 11.83 CLI for webpack must be installed.
#0 11.83 webpack-cli (https://github.com/webpack/webpack-cli)
#0 11.83
#0 11.83 We will use "npm" to install the CLI via "npm install -D webpack-cli".
#0 11.83 Do you want to install 'webpack-cli' (yes/no):
I tried to install webpack-cli separately but can't seem to get it working.
All the guides I've seen seem to say that devDependencies are not needed for the build. Also seems like setting NODE_ENV to production turns on some optimizations, so I wanted to add that. Without NODE_ENV build is running normally, because it adds devDeps I assume.
Am I doing something wrong here or do I need devDeps after all?
Dockerfile:
FROM node:16-alpine as build
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm install -g webpack-cli && npm run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
docker-compose:
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile
ports:
- '80'
networks:
- default
package.json scripts:
"build": "webpack --config webpack-prod.config.ts",
"start": "webpack serve --config webpack-dev.config.ts --progress"
You probably need the development dependencies installed to run your local build sequence. This can include things like Webpack, the Typescript transpiler, and other tools that you need to build the application into static files but not necessarily to run it. The package.json "devDependencies": are needed for the build.
If your npm run build sequence behaves differently in production mode, then you need to set $NODE_ENV after you install the packages from your package.json file.
FROM node:16-alpine as build
WORKDIR /app
COPY package.json package-lock.json ./ # don't forget package-lock.json!
RUN npm ci # including devDependencies
COPY . .
ENV NODE_ENV=production # only after `npm ci`
RUN npm run build
FROM nginx:alpine # unchanged
COPY --from=build /app/build /usr/share/nginx/html
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
Since you're building a pure Web application, this is enough. The recipe is a little bit more complicated if it's a server-side application: you need to RUN npm ci twice, once including devDependencies in an earlier stage to build the application, and once with NODE_ENV=production when you're actually going to run it.

Connecting to React docker container on port 80

I'm trying to deploy a React app as part of a docker compose. It works fine if I deploy on port 3000, but when I use port 80, I cannot connect. If I run npm start manually, either config works fine, but I cannot access the port 80 version when running as a docker image.
I've tried adding EXPOSE 80 to the dockerfile, but it did not seem to have any effect. Can someone point out the error in my config?
Dockerfile:
FROM node:17-alpine
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json ./
COPY package-lock.json ./
RUN npm install
RUN npm install react-scripts#5.0.0 -g
COPY . .
CMD ["npm", "start"]
docker-compose.yaml
version: "3.8"
services:
solvle:
build: ./
container_name: solvle_c
ports:
- '8081:8081'
solvle_front:
build: ./solvle-front
container_name: solvle_front_c
ports:
- '80:80'
stdin_open: true
tty: true
package.json fragment
"scripts": {
"start": "set PORT=80 && react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
For linux you should set port in this way:
"start": "export PORT=80 && react-scripts start"
Another solution is create a file with name .env (documentation) in the main directory and set PORT variable to desired port number:
PORT=80
One more solution.
You could use cross-env to set the port:
npm install cross-env -D
and then modify start script package.json:
"start": "cross-env PORT=80 react-scripts start",
p.s.
But for deploy react app with docker I woud recomend you to use nginx.
p.p.s.
The EXPOSE instruction in dockerfile does not actually publish the port. It functions as a type of documentation. expose documentation

ReactJS + Docker-Compose ERROR | "Could not find a required file"

I have a ReactJS application which has been dockerized. The application is built into a docker image and run on a container for development also using docker-compose tool. This works well when I use it with Docker for Windows. Below is the package.json, it is a very old reactjs scaffolding.
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"react": "^16.8.0",
"react-dom": "^16.8.0",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.2",
"react-listbox":"^1.2.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"devDependencies": {
"enzyme": "^3.8.0",
"enzyme-adapter-react-16": "^1.7.1"
}
}
Folder Structure of the Client Code (Approximate Idea) -
client
-- public
- index.html
-- src
- App.js
package.json
Dockerfile
# base image
FROM node:11.6.0-alpine
# set working directory
WORKDIR /usr/src/app
# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH
# install and cache app dependencies
COPY package.json /usr/src/app/package.json
RUN npm install
# start app
CMD ["npm", "start"]
docker-compose-dev.yml
version: '3.7'
services:
client:
build:
context: ./services/client
dockerfile: Dockerfile
volumes:
- './services/client:/usr/src/app' #(map) outside: inside the docker
- '/usr/src/app/node_modules'
ports:
- 3007:3000
environment:
- NODE_ENV=development
But when I try to push this docker image to a repository and then use it to deploy into a cloud container (possibly, a unix based system), the deployment fails with NPM ERR (as described below).
STDERR
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! client#0.1.0 start: `react-scripts start`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the client#0.1.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-03-11T03_53_28_432Z-debug.log
STDOUT
> client#0.1.0 start /usr/src/app
> react-scripts start
Could not find a required file.
Name: index.html
Searched in: /usr/src/app/public
It fails saying the index.html is not found when I am quite sure, the file is under /public/ which gets mounted to the dockerized image.
NOTE - I know the fact that this is not the way the reactjs code should be deployed on server. It should be through a web server like nginx. But the legacy team had little knowledge about the front end development. Please help regardless.
You are mounting client folder as a volume in the docker image. So, where ever you deploy the docker image, it will expect the volume to be mounted. Instead, you can copy the folder to docker image and make it self contained.
FROM node:11.6.0-alpine
# set working directory
WORKDIR /usr/src/app
# add `/usr/src/app/node_modules/.bin` to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH
# install and cache app dependencies
COPY public /usr/src/app/public
COPY src /usr/src/app/src
COPY package.json /usr/src/app/package.json
RUN npm install
# start app
CMD ["npm", "start"]
your docker-compose-dev.yml will be:
version: '3.7'
services:
client:
build:
context: ./services/client
dockerfile: Dockerfile
ports:
- 3007:3000
environment:
- NODE_ENV=development

Docker stuck at npm install

I have a project that I want to dockerize. I run npm install and npm build with no problem on my computer, but it has some problems when I build with Docker.
Docker output:
Sending build context to Docker daemon 56.96MB
Step 1/7 : FROM node:12.2.0-alpine
---> f391dabf9dce
Step 2/7 : WORKDIR /app
---> Using cache
---> b50a8efbf074
Step 3/7 : ENV PATH /app/node_modules/.bin:$PATH
---> Using cache
---> 3358967a13ab
Step 4/7 : COPY package.json /app/package.json
---> Using cache
---> 851ac31a0adb
Step 5/7 : RUN npm install
---> Running in 8cc36a435cec
npm WARN deprecated core-js#1.2.7: core-js#<2.6.8 is no longer maintained. Please, upgrade to core-js#3 or at least to actual version of core-js#2.
It is stuck in this here:
Dockerfile:
# base image
FROM node:12.2.0-alpine
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# install and cache app dependencies
COPY package.json /app/package.json
RUN npm install
RUN npm install react-scripts#3.0.1 -g --silent
# start app
CMD ["npm", "start"]
I have done this with other dockerfiles, but the result was the same.
package.json:
{
"name": "front",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"bootstrap": "^4.3.1",
"express": "^4.17.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-router": "^5.0.0",
"react-router-dom": "^5.0.0",
"react-scripts": "2.1.8"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
So, this might be a temporary solution till this is properly addressed, but you can use
npm config set registry http://registry.npmjs.org/
I have used it for docker environment and it worked fine.
when ever you run docker run my-image it will run in a new container and previous container remain unused,
we can use docker build location-of-the-Dockerfile --no-cache switch to not using cached images but it didn't work for me
in my case, removing unused containers and images fixed the problem ,
remove all containers > docker rm $(docker ps -aq)
remove all images if you want >> docker image rm $(docker images -q)
I had the same issue. I just waited for 1 hour and it went to the next step.
Edit :
While building the npm install downloads all the packages and it takes time to do that, it depends on the size of your application how long will it take.

React app deploy failure on github

Can Anyone help me out that how can i deploy my react app on github. I have added all required dependecny in my package.json file with using of updated react modules.
Below is my package.json file :
{
"name": "git-sample-react",
"version": "0.1.0",
"private": true,
"homepage": "https://ababsheck.github.io/first-react-sample/",
"dependencies": {
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-scripts": "1.1.4"
},
"scripts": {
"predeploy": "npm run build",
"deploy": "gh-pages -d build",
"deploy": "gh-pages -b master -d build",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"devDependencies": {
"gh-pages": "^1.2.0"
}
}
npm run deploy issue : github
Failed to get remote.origin.url (task must either be run in a git repository with a configured origin remote or must be configured with the "repo" option).
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! git-sample-react#0.1.0 deploy: `gh-pages -b master -d build`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the git-sample-react#0.1.0 deploy script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\abhis\AppData\Roaming\npm-cache\_logs\2018-08-07T12_21_21_735Z-debug.log
I had the same issue, deploying react app in GitHub and resolved this issues with the following steeps:
Run the command in project folder git remote add origin <url>, with the URL of your repository on GitHub.
Run the command npm install --save-dev gh-pages.
Run the npm run build.
Run the command npm run deploy.
Change the branch in GitHub where you deploy see the image below. Under Source must be gh-pages branch.
I also have added the "homepage": "https://ababsheck.github.io/first-react-sample/",
before the script like:
"homepage": "https://ababsheck.github.io/first-react-sample/",
"scripts": {
"predeploy": "npm run build",
...// the rest of the code
Best approach
git init
git remote add origin <repo_link>
yarn add gh-pages
yarn build
yarn deploy
Now go to your Github and update the
Settings-->Github Pages-->source (change to gh-pages branch)-->root-->Save
and then check the link/homepage generated.

Resources