-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
react-node-mongodb #59
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First thank you very much for your contribution, the community asked for such sample #50 👍
Don't forget to update the main README.md to add your sample in the applications list 🙏
Few things to rename:
- the main directory as
react-express-mongodb
because you use an express server for the backend part - the
server
directory tobackend
to keep consistency between the samples?
As you will see, we want to keep README.md
as close as possible of the other samples, but you're amazing documentation shouldn't be drop, so we'll update of contribution guide and add template with some inspiration of work 🙏
const mongoose = require('mongoose'); | ||
const {log} = require('../utils/helpers/logger'); | ||
|
||
exports.connect = () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the MongoDB server isn't up and ready, the server will fail to start
Maybe you can try something like that
exports.connect = (app) => {
const options = {
useNewUrlParser: true,
autoIndex: false, // Don't build indexes
reconnectTries: 30, // Retry up to 30 times
reconnectInterval: 500, // Reconnect every 500ms
poolSize: 10, // Maintain up to 10 socket connections
// If not connected, return errors immediately rather than waiting for reconnect
bufferMaxEntries: 0
}
const connectWithRetry = () => {
console.log('MongoDB connection with retry')
mongoose.connect(process.env.MONGODB_URI, options).then(()=>{
console.log('MongoDB is connected');
app.emit('ready');
}).catch(err=>{
console.log('MongoDB connection unsuccessful, retry after 2 seconds.')
setTimeout(connectWithRetry, 2000)
})
}
connectWithRetry();
};
Just don't forget to pass the app to the function call to emit the readiness event 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Hi there,
First thank you so much for the detailed review. Your comments against each
item is honored, and I'll surely update them by this weekend.
I'm glad to be working on such a great technology that is backed by a great
& active community 😊
I also attended the latest webinar of
'Future of compose webinar'
…On Mon, Apr 27, 2020, 9:14 PM Guillaume Lours ***@***.***> wrote:
***@***.**** requested changes on this pull request.
First thank you very much for your contribution, the community asked for
such sample #50 <#50> 👍
Few things to rename:
- the main directory as react-express-mongodb because you use an
express server for the backend part
- the server directory to backend to keep consistency between the
samples?
As you will see, we want to keep README.md as close as possible of the
other samples, but you're amazing documentation shouldn't be drop, so we'll
update of contribution guide and add template with some inspiration of work
🙏
------------------------------
In react-node-mongodb/.env
<#59 (comment)>:
> @@ -0,0 +1,3 @@
+NODE_PORT=3000
Because this repository is dedicated to show and propose ready to start
application, we try to keep things explicit, that's why we prefer to use
default value in the docker-compose.yml
------------------------------
In react-node-mongodb/.dockerignore
<#59 (comment)>:
> @@ -0,0 +1,3 @@
+server/node_modules
+npm-debug.log
+server/logs/
server/logs/ is needed by the the backend server or you got the following
error
app | throw er; // Unhandled 'error' event
app | ^
app |
app | Error: ENOENT: no such file or directory, open '/usr/src/app/logs/project.log'```
So you need to add the logs directory in the server one, this issue to the
way volume are working
<https://docs.docker.com/engine/reference/builder/#notes-about-specifying-volumes>
------------------------------
In react-node-mongodb/.gitignore
<#59 (comment)>:
> @@ -0,0 +1,6 @@
+frontend/node_modules/
+server/node_modules/
+.idea/
+data
+server/logs
+server/logs/
You need to keep the server/logs directory to avoid error during the
backend startup
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> @@ -0,0 +1,285 @@
+# Docker starter with Node JS, React and MongoDB. All in a single repo
What a well describe README.md file 👏
It's give us an idea to propose a template to describe the application and
the services used
I know it's a lot of work you did, and we don't want to loose that, but we
also want to keep a consistent description of samples README.md
So I suggest you to extract the service documentation to a dedicated
README.md in the service directory and keep the same "template" for the
application (like this one for example
<https://github.com/docker/awesome-compose/tree/master/react-java-mysql>)
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> +## Prerequisite
+
+For this demo to work, [Docker](http://docker.com) and [git](https://git-scm.com/) needs to be installed on your local(host) machine.
Not necessary, there is already a Prerequisites section in the main
README.md of the repository
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> +#### 1. Clone the repo
+We used two DockerFiles one for frontend and other for backend.
+First we will get through the `Dockerfile` of frontend and backend then `docker-compose file`.
Not necessary (that's why we display a directory tree of the application)
and btw it's false because you'll clone the awesome-compose project not
this subdirectory directly 😉
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> +#### 2. Snippet of backend(Node.js)`DockerFile`
+
+You will find this `DockerFile` file in the root directory of the project.
+
+```bash
+FROM node:10
+
+#Argument that is passed from docer-compose.yaml file
+ARG NODE_PORT
+
+#Echo the argument to check passed argument loaded here correctly
+RUN echo "Argument port is : $NODE_PORT"
+
+# Create app directory
+WORKDIR /usr/src/app
+
+#COPY . .
+COPY . .
+
+# Install app dependencies
+# A wildcard is used to ensure both package.json AND package-lock.json are copied
+# where available ***@***.***+)
+RUN npm install
+
+
+#In my case my app binds to port NODE_PORT so you'll use the EXPOSE instruction to have it mapped by the docker daemon:
+
+EXPOSE ${NODE_PORT}
+
+CMD npm run dev
+```
+
+##### 2.1 Explanation of backend(Node.js) `DockerFile`
+
+- The first line tells Docker to use another Node image from the [DockerHub](https://hub.docker.com/). We’re using the official Docker image for Node.js and it’s version 10 image.
+
+- On second line we declare argument `NODE_PORT` which we will pass it from `docker-compose`.
+
+- On third line we log to check argument is successfully read
+
+- On fourth line we sets a working directory from where the app code will live inside the Docker container.
+
+- On fifth line, we are copying/bundling our code working directory into container working directory on line three.
+
+- On line seven, we run npm install for dependencies in container on line four.
+
+- On Line eight, we setup the port, that Docker will expose when the container is running. In our case it is the port which we define inside `.env` file, read it from `docker-compose` then passed as a argument to the (backend)`DockerFile`.
+
+- And in last, we tell docker to execute our app inside the container by using node to run `npm run dev. It is the command which I registered in __package.json__ in script section.
+
+###### 📋 `Note: For development purpose I used __nodemon__ , If you need to deploy at production you should change CMD from __npm run dev__ to __npm start__.`
Should move in a dedicated README.md in the server directory and add a
link to this new file at the bottom of this file
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> +#### 3. Snippet of frontend(ReactJS)`DockerFile`
+
+You will find this `DockerFile` inside **frontend** directory.
+
+```bash
+# Create image based on the official Node image from dockerhub
+FROM node:10
+
+#Argument that is passed from docer-compose.yaml file
+ARG FRONT_END_PORT
+
+# Create app directory
+WORKDIR /usr/src/app
+
+#Echo the argument to check passed argument loaded here correctly
+RUN echo "Argument port is : $FRONT_END_PORT"
+
+# Copy dependency definitions
+COPY package.json /usr/src/app
+
+# Install dependecies
+RUN npm install
+
+# Get all the code needed to run the app
+COPY . /usr/src/app
+
+# Expose the port the app runs in
+EXPOSE ${FRONT_END_PORT}
+
+# Serve the app
+CMD ["npm", "start"]
+```
+##### 3.1 Explanation of frontend(ReactJS) `DockerFile`
+
+Frontend `DockerFile` is almost the same as Backend `DockerFile`. The
+only difference is argument name.
Should move in a dedicated README.md in the frontend directory and add a
link to this new file at the bottom of this file
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> +EXPOSE ${FRONT_END_PORT}
+
+# Serve the app
+CMD ["npm", "start"]
+```
+##### 3.1 Explanation of frontend(ReactJS) `DockerFile`
+
+Frontend `DockerFile` is almost the same as Backend `DockerFile`. The
+only difference is argument name.
+
+Now lets understand the `docker-compose` file
+
+#### 4. Snippet of `docker-compose`
+
+```bash
+version: "2"
Please use at least a version 3.7 of the docker compose file specification
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> +##### 4.1 Explanation of `docker-compose`
+
+__Version__
+
+The first line defines the version of a file. It sounds confusing 😕. What is meant by version of file ??
+
+💊 The Compose file is a YAML file defining services, networks, and volumes for a Docker application. So it is only a version of describing compose.yaml file. There are several versions of the Compose file format – 1, 2, 2.x, and 3.x.
+
+__Services__
+
+Our main goal to create a containers, it starts from here. As you can see there are three services(Docker images):
+- First is __frontend__
+- Second is __app__ which is __backend - NodeJS__. I used a name app here, it's totally on you to name it __backend__.
+- Third is __MongoDB__.
+
+##### 4.1.1 Service app (backend - NodeJS)
+
+We make image of app from our `DockeFile`, explanation below.
+
+__Explanation of service app__
+
+- Defining a **nodejs** service as __app__.
+- We named our **node server** container service as **app**. Assigning a name to the containers makes it easier to read when there are lot of containers on a machine, it can aslo avoid randomly generated container names. (Although in this case, __container_name__ is also __app__, this is merely personal preference, the name of the service and container do not have to be the same.)
+- Docker container starts automatically if its fails.
+- Building the __app__ image using the Dockerfile from the current directory and passing an argument to the
+backend `DockerFile`.
+- Mapping the host port to the container port.
+- Why we used `${}` ?. It is the way to read `environment` variables from `.env` file inside `docker-compose`. But it should be in the same directory of `docker-compose`.
+
+##### 4.1.2 Service mongo
+
+We add another service called **mongo** but this time instead of building it from `DockerFile` we write all the instruction here directly. We simply pull down the standard __mongo image__ from the [DockerHub](https://hub.docker.com/) registry as we have done it for Node image.
+
+__Explanation of service mongo__
+
+- Defining a **mongodb** service as __mongo__.
+- Pulling the mongo 4.2.0 image image again from [DockerHub](https://hub.docker.com/).
+- Mount our current db directory to container.
+- For persistent storage, we mount the host directory ( just like I did it in **Node** image inside `DockerFile` to reflect the changes) `/data` ( you need to create a directory in root of your project in order to save changes to locally as well) to the container directory `/data/db`, which was identified as a potential mount point in the `mongo Dockerfile` we saw earlier.
+- Mounting volumes gives us persistent storage so when starting a new container, Docker Compose will use the volume of any previous containers and copy it to the new container, ensuring that no data is lost.
+- Finally, we link/depends_on the app container to the mongo container so that the mongo service is reachable from the app service.
+- In last mapping the host port to the container port.
+
+:key: `If you wish to check your DB changes on your local machine as well. You should have installed MongoDB locally, otherwise you can't access your mongodb service of container from host machine.`
+
+:white_check_mark: You should check your __mongo__ version is same as used in image. You can see the version of __mongo__ image in `docker-compose `file, I used __image: mongo:4.2.0__. If your mongo db version on your machine is not same then furst you have to updated your local __mongo__ version in order to works correctly.
+
Can you move all this description after the common template?
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> +- Mount our current db directory to container.
+- For persistent storage, we mount the host directory ( just like I did it in **Node** image inside `DockerFile` to reflect the changes) `/data` ( you need to create a directory in root of your project in order to save changes to locally as well) to the container directory `/data/db`, which was identified as a potential mount point in the `mongo Dockerfile` we saw earlier.
+- Mounting volumes gives us persistent storage so when starting a new container, Docker Compose will use the volume of any previous containers and copy it to the new container, ensuring that no data is lost.
+- Finally, we link/depends_on the app container to the mongo container so that the mongo service is reachable from the app service.
+- In last mapping the host port to the container port.
+
+:key: `If you wish to check your DB changes on your local machine as well. You should have installed MongoDB locally, otherwise you can't access your mongodb service of container from host machine.`
+
+:white_check_mark: You should check your __mongo__ version is same as used in image. You can see the version of __mongo__ image in `docker-compose `file, I used __image: mongo:4.2.0__. If your mongo db version on your machine is not same then furst you have to updated your local __mongo__ version in order to works correctly.
+
+#### 5. Command to Build and Run the Docker images/containers
+
+We can now navigate to the project directory, open up a terminal window and run :
+
+```bash
+$ sudo docker-compose up
I prefer to not using sudo 😅
------------------------------
In react-node-mongodb/README.md
<#59 (comment)>:
> +#### 6. Verification of Server is running and DB is connected
+
+Now to check an api of todos you hit the api using __curl__. Curl is need to be installed on your machine. Otherwise you should use postman for hitting an api.
+
+To Install curl run the command :
+
+```bash
+$ sudo apt-get update
+```
+
+then
+
+```bash
+$ sudo apt-get install curl
+```
+
+After installing curl run the command:
+
+```bash
+$ curl http://localhost:3000/api
+```
+
+If everything works fine you will get the response
+
+`{"code":200,"success":true,"message":"Successfully completed","todos":[]}`
+
+Right now there is no todos in DataBase.
+
+To insert some todos in DB hit the post api of todos e.g:
+
+```bash
+$ curl -d '{"text":"Testing todo"}' -H "Content-Type: application/json" -X POST http://localhost:3000/api/todos
+```
+
+I added the text for todo is "testing todo" you can write any text you want. You can add much todos as you want. To check todo is insert in DB, call the `get` todo api again as we called earlier and this time you will see the added todo in todos array.
+
+`{"code":200,"success":true,"message":"Successfully completed","todos":[{"_id":"5da71f426e17e00020a67539","text":"Testing todo","__v":0}]}`
+
I don't think we need this section, users should be able to check
everything is ok just by issuing their browser
------------------------------
In react-node-mongodb/docker-compose.yml
<#59 (comment)>:
> @@ -0,0 +1,36 @@
+version: "2"
Please use a least version 3.7 of the docker compose file specification
------------------------------
In react-node-mongodb/docker-compose.yml
<#59 (comment)>:
> @@ -0,0 +1,36 @@
+version: "2"
+services:
+ frontend:
+ build:
+ context: frontend
+ args:
+ FRONT_END_PORT: ${FRONT_END_PORT}
Declare a default value instead of using by the .env file
------------------------------
In react-node-mongodb/docker-compose.yml
<#59 (comment)>:
> + args:
+ FRONT_END_PORT: ${FRONT_END_PORT}
+ ports:
+ - ${FRONT_END_PORT}:${FRONT_END_PORT}
+ volumes:
+ - ./frontend:/usr/src/app
+ - /usr/src/app/node_modules
+ container_name: front-container
+ restart: always
+ app:
+ container_name: app
+ restart: always
+ build:
+ context: server
+ args:
+ NODE_PORT: ${NODE_PORT}
Declare a default value instead of using by the .env file
------------------------------
In react-node-mongodb/docker-compose.yml
<#59 (comment)>:
> + NODE_PORT: ${NODE_PORT}
+ ports:
+ - ${NODE_PORT}:${NODE_PORT}
+ volumes:
+ - ./server:/usr/src/app
+ - /usr/src/app/node_modules
+ depends_on:
+ - mongo
+ mongo:
+ container_name: mongo
+ restart: always
+ image: mongo:4.2.0
+ volumes:
+ - ./data:/data/db
+ ports:
+ - ${MONGODB_PORT}:${MONGODB_PORT}
Declare a default value instead of using by the .env file
------------------------------
In react-node-mongodb/docker-compose.yml
<#59 (comment)>:
> + NODE_PORT: ${NODE_PORT}
+ ports:
+ - ${NODE_PORT}:${NODE_PORT}
+ volumes:
+ - ./server:/usr/src/app
+ - /usr/src/app/node_modules
+ depends_on:
+ - mongo
+ mongo:
+ container_name: mongo
+ restart: always
+ image: mongo:4.2.0
+ volumes:
+ - ./data:/data/db
+ ports:
+ - ${MONGODB_PORT}:${MONGODB_PORT}
Maybe you can declare basic networks and use them to avoid direct
connection between the frontend service and MongoDB service? (here an
example
<https://github.com/docker/awesome-compose/blob/master/react-express-mysql/docker-compose.yaml>
)
------------------------------
In react-node-mongodb/frontend/.dockerignore
<#59 (comment)>:
> @@ -0,0 +1,3 @@
+node_modules
+npm-debug.log
+server/logs/
Should be kept
------------------------------
In react-node-mongodb/frontend/Dockerfile
<#59 (comment)>:
> @@ -0,0 +1,26 @@
+# Create image based on the official Node image from dockerhub
+FROM node:10
NodeJs 10 is pretty old, maybe we can switch to a node:13.13.0-stretch?
And you can improve this dockerfile with multistage build, check here for
a good example
<https://github.com/docker/awesome-compose/blob/master/react-express-mysql/frontend/Dockerfile>
------------------------------
In react-node-mongodb/frontend/README.md
<#59 (comment)>:
> @@ -0,0 +1,68 @@
+This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
Replace the default README of react by the good description you have done
in the application README
------------------------------
In react-node-mongodb/frontend/README.md
<#59 (comment)>:
> @@ -0,0 +1,68 @@
+This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
( or you can rename this file to keep it if you want)
------------------------------
In react-node-mongodb/frontend/package.json
<#59 (comment)>:
> @@ -0,0 +1,34 @@
+{
You need to do a npm update and npm audit fix to fix some security issues
and use the latest version of node-sass and react libs
------------------------------
In react-node-mongodb/server/Dockerfile
<#59 (comment)>:
> @@ -0,0 +1,27 @@
+FROM node:10
Like for frontend Dockerfile, you can take a look at this example
<https://github.com/docker/awesome-compose/blob/master/react-express-mysql/frontend/Dockerfile>
and update to a node:13.13.0-stretch-slim (we can use a slim one because
no need of Python for the backend)
------------------------------
In react-node-mongodb/server/db/index.js
<#59 (comment)>:
> @@ -0,0 +1,16 @@
+/**
+ * Created by Syed Afzal
+ */
+const mongoose = require('mongoose');
+const {log} = require('../utils/helpers/logger');
+
+exports.connect = () => {
If the MongoDB server isn't up and ready, the server will fail to start
Maybe you can try something like that
exports.connect = (app) => {
const options = {
useNewUrlParser: true,
autoIndex: false, // Don't build indexes
reconnectTries: 30, // Retry up to 30 times
reconnectInterval: 500, // Reconnect every 500ms
poolSize: 10, // Maintain up to 10 socket connections
// If not connected, return errors immediately rather than waiting for reconnect
bufferMaxEntries: 0
}
const connectWithRetry = () => {
console.log('MongoDB connection with retry')
mongoose.connect(process.env.MONGODB_URI, options).then(()=>{
console.log('MongoDB is connected');
app.emit('ready');
}).catch(err=>{
console.log('MongoDB connection unsuccessful, retry after 2 seconds.')
setTimeout(connectWithRetry, 2000)
})
}
connectWithRetry();
};
Just don't forget to pass the app to the function call to emit the
readiness event 😉
------------------------------
In react-node-mongodb/server/config/messages.js
<#59 (comment)>:
> + FORBIDDEN: {
+ code: 403,
+ message: 'You are not authorized to complete this action',
+ success: false,
+ },
+ BAD_REQUEST: {
+ code: 400,
+ message: 'Bad request. Please try again with valid parameters',
+ success: false,
+ },
+ IN_COMPLETE_REQUEST: {
+ code: 422,
+ message: 'Required parameter missing',
+ success: false,
+ },
+};
nit: add a new line at the end of the file
------------------------------
In react-node-mongodb/server/package.json
<#59 (comment)>:
> @@ -0,0 +1,27 @@
+{
Same here, update your dependencies and run an audit to be sure there
isn't any security issues to fix (and there's some ^^)
------------------------------
In react-node-mongodb/server/server.js
<#59 (comment)>:
> + */
+require('./config/config');
+
+const express = require('express');
+const path = require('path');
+const cookieParser = require('cookie-parser');
+const bodyParser = require('body-parser');
+const cors = require('cors');
+const db = require('./db');
+
+
+
+const app = express();
+
+//connection from db here
+db.connect();
If you use the previous snippet in db/index.js don't forget to pass app
to the function
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#59 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGG2MYVS6KYO2U3VQEPCUFTROWVQFANCNFSM4MPJXOLQ>
.
|
Hi there, First thank you so much for the detailed review. Your comments against each item is honored, and I'll surely update them by this weekend. I'm glad to be working on such a great technology that is backed by a great & active community 😊 I also attended the latest webinar of |
Don't forget to sign off your commits 😉 |
@glours I am done with all the changes. Please have a look in it and let me know if there is anything remaining. Thanks |
I'll try to check tomorrow 👍 |
Sure
…On Tue, May 5, 2020, 1:30 AM Guillaume Lours ***@***.***> wrote:
I'll try to check tomorrow 👍
Thanks
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#59 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGG2MYWHROHUVX347LPOTNLRP4QUPANCNFSM4MPJXOLQ>
.
|
Hi @glours, hope you are doing well, Any update? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry for the delay, just few things to change but I think we're almost done 👌
Thanks for your patience 🙏
Signed-off-by: Afzal <sah.afzal@gmail.com>
@glours I am done with all the changes. Please have a look |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks @123afzal
Fix #50 |
Signed-off-by: Afzal <sah.afzal@gmail.com>
I have created the one more sample of Docker Compose applications with multiple integrated services,
Services which I used is "react-node-mongodb". It will be an honor for me to contribute in docker community.
Let me know if you want some changes ?