As there are loads of tutorials out there that go over the specifics of what everything does. I’m going to try and keep this short sweet and simple. This assumes you have basic docker knowledge. I will be touching on any issue I had come across and what I’ve done to resolve them.
In the end, you will have a docker-compose driven MERN stack with hot reload
This docker app will have the following folder structure.
root-folder
|>frontend
Dockerfile
{front end files}
|>server
Dockerfile
{server end files}
docker-compose.yml
From inside the frontend folder run npx create-react-app .
This command creates a full react app for you. With various folders, files, and configurations out of the box. This is the easiest way to do it if you want to start with a skeleton project.
After this command is done run yarn start
or npm start
. If you are able to access and edit the site + see hot reloading. then you are good to keep moving.
While still in the frontend folder, create a file named Dockerfile and paste the following
FROM node:alpine
WORKDIR /app
COPY package.json package.json
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm","run", "start"]
This docker file does the following.
docker build -t react-app .
docker run -p 3000:3000 react-app
For the server, we will be using a similar command to get us a skeleton project. Both the server setup and frontend setup are very similar
From inside the server folder run npx express-generator .
This command creates a full express app for you. With various folders, files, and configurations out of the box. This is the easiest way to do it if you want to start with a skeleton project.
You will need to create a .env file and put PORT=5000
for the express app to start on the correct port.
After this command is done run npm install -g nodemon
to enable hot reloading.
nodemon ./bin/www
to start the express app. You should then be able to access the site on localhost and ensure everything is working.
While still in the server folder, create a file named Dockerfile and paste the following
FROM node:alpine
WORKDIR /app
COPY package.json package.json
RUN npm install
COPY . .
EXPOSE 5000
RUN npm install -g nodemon
CMD [ "nodemon", "./bin/www" ]
This docker file does the following.
You can check to see if everything is working by running the following commands
docker build -t myapp-server .
docker run p 5000:5000 myapp-server
Now in the main folder create a docker-compose.yml and past the following.
version: '3.7'
services:
server:
tty: true
build:
context: ./server
dockerfile: Dockerfile
image: myapp-server
container_name: myapp-node-server
command: npm start
volumes:
- ./server:/app
- /app/node_modules
ports:
- "5000:5000"
depends_on:
- mongo
env_file: ./server/.env
environment:
- NODE_ENV=development
networks:
- app-network
mongo:
image: mongo
volumes:
- data-volume:/data/db
ports:
- "27017:27017"
networks:
- app-network
client:
tty: true
build:
context: ./frontend
dockerfile: Dockerfile
image: myapp-client
container_name: myapp-react-client
command: npm start
volumes:
- ./frontend:/app
- /app/node_modules
depends_on:
- server
ports:
- "3000:3000"
networks:
- app-network
environment:
- CHOKIDAR_USEPOLLING=true
networks:
app-network:
driver: bridge
volumes:
data-volume:
node_modules:
web-root:
driver: local
This may look like a lot, be reading through the file is very self-explaining.
You can now run the file with
docker-compose build
docker-compose up
You should now be able to visit localhost:3000 and see your react app + hot reloading. Visit localhost:5000 and see your express app + hot reloading. Lastly, you should be able to connect to your mongo server on port 27017
While doing this myself self I ran into a problem with the react app not hot reloading.
It is very important to have
environment:
- CHOKIDAR_USEPOLLING=true
tty: true
in the file for the client section.
There is currently a bug in react-scripts 3.4.3 the breaks building in docker if the terminal is not open.
If you need to debug the express server, I would recommend commenting on the client section. You will then be able to see the output from the express server. This can sometimes lead you to any issues it is having.
If you keep getting module not found errors
. Make sure the module is in your package.json. Make sure you rebuilt the docker-compose. If that fails try editing the Dockerfile for the app that is missing the module. adding node install -g module-name
allows you to install it globally. While this is not the best option, it can be the fastest and least frustrating.