Let's do it
We are going to create a MERN Stack boilerplate using docker which can serve as a base to create other apps as well.
A quick note: react is ready to go in production. but backend (nodejs) could be improved further. So you could also focus only on react!
Feel free to comment if you have optimitized nodejs API's using pm2 etc.
Now let's create our project.
project
└───backend
- index.js
- .env
└───frontend
First we are going to create our backend and frontend and then we will move on to dockerize them.
Lets setup our backend first.
$ cd backend
$ npm init
If you want to skip these questions
$ npm init -y
It createspackage.json
. The package.json file holds some basic information about your application as well as metadata about your app. Add inside package.json
add:(enables ES 6 modules, u can use import syntax)
"type": "module",
Let's install express server.
$ npm i express
$ npm i dotenv
Replace .env
with below:
NODE_ENV = development
PORT = 5000
Replace index.js
with below code
import express from 'express'
import dotenv from 'dotenv'
dotenv.config()
const app = express()
app.get('/', (req, res) => {
res.send('API is running')
})
const PORT = process.env.PORT || 5000
app.listen(PORT, () =>
console.log(`
Server running in ${process.env.NODE_ENV} mode on ${PORT} Port`)
)
Test if our app is running
$ node backend/index.js
It should be available at http://localhost:5000/
Lets do frontend now.
Make sure you are inside frontend folder. Let's creates a react app. But hot reloading does not work well with react-scripts @5.0.0
(At the time of writing)
$ cd frontend
$ npx create-react-app ./
So for now you could use this.
$ cd root
$ npx create-react-app ./client --scripts-version 4.0.3
$ cd client
$ npm run start
our app should be available at https://localhost:3000/
Now we are going to dockerize our app.
Docker file Server
$ cd backend
Create a .dockerignore
file.
node_modules
Dockerfile
.gitignore
.git
Create a Dockerfile
without any extension.
FROM node:16.14.0-slim
#create app directory inside docker
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
#Bundle source code
COPY . .
EXPOSE 5000
CMD ["npm","run","dev"]
let's build our docker image Server
$ docker build -t backend .
To run our container
$ docker run -p port 4000:5000 backend
To run with hot reloading use this command and remove container at the end.
$ docker run --rm -it -p 5000:5000 -v ${PWD}:/usr/src/app --name app-backend backend
available at https://localhost:4000/
Docker file frontend
$ cd frontend
Create a .dockerignore
file.
node_modules
Dockerfile
.gitignore
.git
Create Dockerfile
without any extension
FROM node:16.14.0-slim
# Working directory
WORKDIR /user/src/frontend
# Install dependencies
COPY package*.json ./
RUN npm install
# Copy local files to frontend folder
COPY . .
EXPOSE 3000
CMD ["npm","start"]
Create Dockerfile.prod
file for production builds
FROM node:16.14.0-slim AS build-stage
ENV NODE_ENV production
# Add a work directory
WORKDIR /user/src/frontend
# ENV PATH /app/node_modules/.bin:$PATH
# Cache and Install dependencies
COPY package*.json ./
# COPY yarn.lock .
RUN npm install --production
# Copy app files
COPY . .
# Build the app
RUN npm run build
FROM nginx:1.21.6-alpine
ENV NODE_ENV production
# Copy built assets from builder
COPY --from=build-stage /user/src/frontend/build /usr/share/nginx/html
# Add your nginx.conf
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
# Expose port
EXPOSE 80
# Start nginx
CMD ["nginx", "-g", "daemon off;"]
Docker Compose
Instead of typing those long command through terminal. Compose files allow us to manage container easily.
Create docker-compose.yml
file
$ cd root
version: '3'
services:
frontend:
container_name: react-dev
build:
context: ./frontend
ports:
- 3000:3000
env_file: ./frontend/.env
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true
volumes:
- ./frontend:/user/src/frontend
- /user/src/frontend/node_modules
Create docker-compose.prod.yml
file for production builds(React only)
$ cd root
version: '3'
services:
frontend:
container_name: react-prod
image: react-prod
build:
context: ./frontend
dockerfile: Dockerfile.prod
ports:
- 1337:80
env_file: ./frontend/.env
Some useful Docker commands
Show all containers in running state.
$ docker ps
or newer version $ docker container ls
To show all running and exited container
$ docker ps -a
or $ docker container --all
Run a container bash session.
$ docker exec -it <container name> bash
Run a image bash session.
$ docker run -it <image name> bash
$ docker run -it backend bash
then$ node -v
prints node version.
To pull base images before using them e.g.
$ docker pull <image name>
$ docker pull node:16.14.0-slim
Run your image (backend) as a container(app-backend).
$ docker run -p 2000:5000 --name app-backend backend
To start existing container.
$ docker container start <container name>
To stop an existing container.
$ docker stop <container name>
To remove a container.
$ docker rm <container name>
To stop all container
$ docker stop $(docker ps -a -q)
To remove all container
$ docker rm $(docker ps -a -q)
MERN Stack template
We are going to create a MERN Stack boilerplate which can be extended for other use cases. Run it locally
or on Docker
.
project
└───backend
└───frontend
└───.env
Lets setup our backend first.
$ cd backend
$ npm init
If you want to skip these questions
$ npm init -y
It creates package.json
. The package.json file holds some basic information about your application as well as metadata about your app. Add inside package.json
add:
"type": "module",
Let's install express server
$ npm i express
$ npm i dotenv
Replace .env
with below:
NODE_ENV = development
PORT = 5000
Replace index.js
with below code
import express from 'express'
import dotenv from 'dotenv'
dotenv.config()
const app = express()
app.get('/', (req, res) => {
res.send('API is running')
}
…ps: somehow the changes in react part is missing from repo. Create a pull request!
LinkedIn: LinkedIn
GitHub: Link ⭐
Fiverr: imidrees ✨
Thanks for reading!
Top comments (1)
I recommend to put that containers and manage with dokku :>