This project demonstrates a MEAN (MongoDB, Express, Angular, NodeJS) stack application running on Docker. It is an ideal starting point for creating a full-stack web application and demonstrates both development and production setups using Docker. Additionally, it showcases using GitHub Actions for building and pushing Docker images to Docker Hub.
The architecture of the application while running:
Clone repo, navigate to root folder and run docker-compose -f 'docker-compose.nginx.yml' up
git clone https://github.com/nitin27may/mean-docker.git
cd mean-docker
docker-compose -f 'docker-compose.nginx.yml' up
This project is organized into several folders, each representing a different component built with popular JavaScript frameworks and libraries:
folder | Description |
---|---|
frontend | frontend app using Angular |
api | api using expressjs |
loadbalancer | load balancer using nginx |
mongo | mongo db image setup |
This application includes features such as user registration, login, and a complete CRUD (Create, Read, Update, Delete) example. It utilizes Angular Routing for navigation and provides REST API samples built with Express.js. The REST services are secured using JWT (JSON Web Tokens), ensuring safe and efficient user authentication.
The frontend of this project is developed using Angular, the "A" in the MEAN stack. For Server-Side Rendering (SSR), we chose the Node.js Alpine image over a lightweight Docker image like Nginx to run the Angular application.
The project includes sample code for various key functionalities, such as:
- User registration
- Login
- Profile Management
- Complete CRUD example for contacts.
Additionally, you'll find examples of implementing authentication guards, services, HTTP interceptors, resolvers, and JWT authentication.
This application is designed to be user-friendly, featuring a functional registration and login page, along with a comprehensive CRUD implementation that showcases Angular Routing and Express.js REST API examples. All REST services are secured using JWT for enhanced security.
For folder structure details refer this link: [Frontend Folder Structure] (/docs/angular-frontend-structure.md)
Dockerfile for Production Dockerfile for Development
In the MEAN stack, the "E" stands for Express.js, which is used to develop all REST services.
This project includes samples for:
- Mongo dB connection and schema validation using Mongoose
- JWT implementation for Authorization
- API routing
- User registration & login APIs
- Complete CRUD example for Contact
For folder structure details refer this link: API Folder Structure
Dockerfile for production Dockerfile for development
We are using Mongodb for database. MongoDB is a cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with optional schemas.
Seed data script Database user creation script
_Note: only if you are using docker. _
We have uses NGINX loadbalancer in case if there is a requirement that frontend and api need to be exposed on same port. For configutration please check nginx.conf
Load balancer (nginx) Dockerfile
Install latest Docker Desktop
You can start the application in debug mode (database, api and frontend) using docker-compose:
git clone https://github.com/nitin27may/mean-docker.git
cd mean-docker
docker-compose -f 'docker-compose.debug.yml' up
It will run fronend http://localhost:4200
and api on http://localhost:3000
. you can also access mongodb on port 27017.
Also, it will automatically refresh (hot reload) your UI for code changes. That is also true for expressjs file changes.
For Production mode, there is 2 options:
git clone https://github.com/nitin27may/mean-docker.git
cd mean-docker
docker-compose -f 'docker-compose.yml' up
or just run beow as docker consider default file name 'docker-compose.yml'
docker-compose up
It will run fronend and api on http://localhost:3000
. you can also access mongodb on port 27017
git clone https://github.com/nitin27may/mean-docker.git
cd mean-docker
docker-compose -f 'docker-compose.nginx.yml' up
It will run fronend and api on http://localhost
. you can aslo access by it's invidual ports. For Frontend http://localhost:4000
and for api http://localhost:3000
.you can also access mongodb on port 27017
The main focus of this project to show case the possible way to run a real application (Mean stack) using docker.
we have considered 3 scenarios:
-
Using 2 containers (docker-compose.yml)
- express: To host Frontend (Angular) and backend api (expressjs) together
- database: To host MongoDB
Note: If in above case we are using MongoDB as managed service then we will require only one container.
version: "3.8" # specify docker-compose version
# Define the services/containers to be run
services:
express: #name of the second service
build: # specify the directory of the Dockerfile
context: .
dockerfile: dockerfile
container_name: mean_angular_express
ports:
- "3000:3000" #specify ports forewarding
# Below database enviornment variable for api is helpful when you have to use database as managed service
environment:
- SECRET=Thisismysecret
- MONGO_DB_USERNAME=admin-user
- MONGO_DB_PASSWORD=admin-password
- MONGO_DB_HOST=database
- MONGO_DB_PORT=
- MONGO_DB_PARAMETERS=?authSource=admin
- MONGO_DB_DATABASE=mean-contacts
links:
- database
database: # name of the third service
image: mongo:latest # specify image to build container from
container_name: mean_mongo
environment:
- MONGO_INITDB_ROOT_USERNAME=admin-user
- MONGO_INITDB_ROOT_PASSWORD=admin-password
- MONGO_DB_USERNAME=admin-user1
- MONGO_DB_PASSWORD=admin-password1
- MONGO_DB=mean-contacts
volumes:
- ./mongo:/home/mongodb
- ./mongo/init-db.d/:/docker-entrypoint-initdb.d/
- ./mongo/db:/data/db
ports:
- "27017:27017" # specify port forewarding
-
Using 4 containers (docker-compose.nginx.yml)
- angular: Application's frontend (Angular)
- express: Application's Rest services (expressjs)
- database: Application database: MongoDB
- nginx: As laod balancer, also expose UI and API on same ports
Note: If in above case we are using MongoDB as managed service then we will require only one container.
version: "3.8" # specify docker-compose version
# Define the services/containers to be run
services:
angular: # name of the first service
build: frontend # specify the directory of the Dockerfile
container_name: mean_angular
ports:
- "4000:4000" # specify port forewarding
environment:
- NODE_ENV=dev
express: #name of the second service
build: api # specify the directory of the Dockerfile
container_name: mean_express
ports:
- "3000:3000" #specify ports forewarding
# Below database enviornment variable for api is helpful when you have to use
# database as managed service
environment:
- SECRET=Thisismysecret
- MONGO_DB_USERNAME=admin-user
- MONGO_DB_PASSWORD=admin-password
- MONGO_DB_HOST=database
- MONGO_DB_PORT=
- MONGO_DB_PARAMETERS=?authSource=admin
- MONGO_DB_DATABASE=mean-contacts
links:
- database
database: # name of the third service
image: mongo:latest # specify image to build container from
container_name: mean_mongo
environment:
- MONGO_INITDB_ROOT_USERNAME=admin-user
- MONGO_INITDB_ROOT_PASSWORD=admin-password
- MONGO_DB_USERNAME=admin-user1
- MONGO_DB_PASSWORD=admin-password1
- MONGO_DB=mean-contacts
volumes:
- ./mongo:/home/mongodb
- ./mongo/init-db.d/:/docker-entrypoint-initdb.d/
- ./mongo/db:/data/db
ports:
- "27017:27017" # specify port forewarding
nginx: #name of the fourth service
build: loadbalancer # specify the directory of the Dockerfile
container_name: mean_nginx
ports:
- "80:80" #specify ports forewarding
links:
- express
- angular
-
Development Mode (docker-compose.debug.yml)
It will run 3 containers which are required for development.
version: "3.8" # specify docker-compose version
# Define the services/containers to be run
services:
angular: # name of the first service
build: # specify the directory of the Dockerfile
context: ./frontend
dockerfile: debug.dockerfile
container_name: mean_angular
volumes:
- ./frontend:/frontend
- /frontend/node_modules
ports:
- "4200:4200" # specify port forewarding
- "49153:49153"
environment:
- NODE_ENV=dev
express: #name of the second service
build: # specify the directory of the Dockerfile
context: ./api
dockerfile: debug.dockerfile
container_name: mean_express
volumes:
- ./api:/api
- /api/node_modules
ports:
- "3000:3000" #specify ports forewarding
environment:
- SECRET=Thisismysecret
- NODE_ENV=development
- MONGO_DB_USERNAME=admin-user
- MONGO_DB_PASSWORD=admin-password
- MONGO_DB_HOST=database
- MONGO_DB_PORT=
- MONGO_DB_PARAMETERS=?authSource=admin
- MONGO_DB_DATABASE=mean-contacts
links:
- database
database: # name of the third service
image: mongo # specify image to build container from
container_name: mean_mongo
environment:
- MONGO_INITDB_ROOT_USERNAME=admin-user
- MONGO_INITDB_ROOT_PASSWORD=admin-password
- MONGO_DB_USERNAME=admin-user1
- MONGO_DB_PASSWORD=admin-password1
- MONGO_DB=mean-contacts
volumes:
- ./mongo:/home/mongodb
- ./mongo/init-db.d/:/docker-entrypoint-initdb.d/
- ./mongo/db:/data/db
ports:
- "27017:27017" # specify port forewarding
Earlier, we were using docker hub autobuild triggers to build images and push to registry (Docker Hub), now it is using github action, we can take an example of frontend image: File : angular-build-and-push.yml
name: Angular Build
on:
push:
branches: master
paths:
- 'frontend/**'
jobs:
main:
runs-on: Ubuntu-20.04
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: frontend/.
file: frontend/Dockerfile
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/mean-angular:latest
secrets: |
GIT_AUTH_TOKEN=${{ secrets.MYTOKEN }}
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
here, DOCKERHUB_USERNAME is your docker hub username and DOCKERHUB_TOKEN, we can generate from account settings (account settings > Security > New Access Token) section from your docker hub accounts and add under your github repo > settings > secrets
- Install latest Node js
- Install Nodemon as global package (To run exprerssjs in development mode)
npm install -g nodemon
- Optional (Install Angular CLI
npm install -g @angular/cli
) - Install Mongodb locally or Signup for a free managed account
- Before running the project make sure that you are able to connect MongoDb , you can use Robo 3T for it
Clone the project and run npm install
in frontend and api folder.
git clone https://github.com/nitin27may/mean-docker.git
cd mean-docker/frontend
npm i
npm start
cd mean-docker/api
npm i
npm start
For passing enviornment variables (database details) in api, Navigate to api folder, rename .env.example
to .env
and update your mongo db details there.
Also, you can run d npm run dev-server
from frontend folder to run frontend and api together.
It will run Api on http://localhost:3000
and frontend on http://localhost:4200
See the open issues for a list of proposed features (and known issues).
Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
Nitin Singh - @nitin27may