Mean Docker Save

A Mean stack (Angular 17.0.3, Expressjs 4.17.1, MongoDB) jump start project with support of docker.

Project README

Mongo Build Expressjs Build Angular Build Nginx Build

MEAN (Stack) using Docker

About (MongoDB - Express - Angular - NodeJS)

The MEAN stack - consisting of MongoDB, Express, Angular, and NodeJS - forms the foundation of a full-stack web application, and this project serves as an ideal starting point for creating one. The project also demonstrates a feasible approach to operating a live application on Docker in both development and production settings. Additionally, it features the use of Github actions to construct and upload images to Docker Hub.

Below is the architecture of the application while it is running.

To Quick Run

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

Demo

https://user-images.githubusercontent.com/8065536/138562565-f601586c-ef38-43b6-8db7-67a4bdefbb96.mp4

Project Folders

The apps written in the following JavaScript frameworks/libraries:

folder Description
frontend frontend app using Angular
api api using expressjs
loadbalancer load balancer using nginx
mongo mongo db image setup

About Project

The web application presented here is uncomplicated yet functional. It features a user registration and login page that are fully operational, as well as a comprehensive demonstration of CRUD (Create, Read, Update, Delete) functionality that incorporates Angular Routing and examples of REST API usage with Express.js. Additionally, the REST services are safeguarded by implementing JWT (JSON Web Tokens) for enhanced security.

Built With

Angular (17.0.3)

The frontend of this project is built with Angular, which is represented by the "A" in MEAN stack. To enable Server Side Rendering (SSR), we opted to use the Node.js Alpine image instead of a lightweight Docker image like Nginx to run the Angular application.

The project includes sample code for various functionalities, such as

  • User registration
  • Login
  • Profile Management
  • Complete CRUD example for contacts.

Additionally, there are samples of code for implementing an authentication guard, services, HTTP interceptors, resolvers, and JWT authentication.

This is a simple web application. It has working user registration, login page and there is a complete example of CRUD which contains example for Angular Routing and exprtess js rest api samples. Also, rest services are secure using JWT.

For folder structure details refer this link: [Frontend Folder Structure] (/docs/angular-frontend-structure.md)

Dockerfile for Production Dockerfile for Development

Expressjs (4.17.1)

In MEAN stack, E stands for Expressjs, all rest services are developed using express js.

It contains sample for:

  1. Mongo dB connection and schema validation using Mongoose
  2. JWT implementation for Authorization
  3. API routing
  4. User registration & login APIs
  5. Complete CRUD example for Contact

For folder structure details refer this link: API Folder Structure

Dockerfile for production Dockerfile for development

Mongo DB

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

NGINX

_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

Getting started

Using Docker

Prerequisite

Install latest Docker Desktop

Development mode:

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.

Production mode:

For Production mode, there is 2 options:

Using 2 containers (Express (frontend and api) and Mongo)
  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

Using 4 containers (Mongo,api, angular and nginx)
  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

About Docker Compose File

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:

  1. 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
  1. 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
  1. 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

Pushing Image to Registry (Github Actions)

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

Without Docker

Prerequisites

  1. Install latest Node js
  2. Install Nodemon as global package (To run exprerssjs in development mode) npm install -g nodemon
  3. Optional (Install Angular CLI npm install -g @angular/cli)
  4. Install Mongodb locally or Signup for a free managed account
  5. Before running the project make sure that you are able to connect MongoDb , you can use Robo 3T for it

Running the Project

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

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

Without Docker

Prerequisites

  1. Install latest Node js
  2. Install Nodemon as global package (To run exprerssjs in development mode) npm install -g nodemon
  3. Optional (Install Angular CLI npm install -g @angular/cli)
  4. Install Mongodb locally or Signup for a free managed account
  5. Before running the project make sure that you are able to connect MongoDb , you can use Robo 3T for it

Running the Project

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

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

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.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

MIT

Contact

Nitin Singh - @nitin27may

Open Source Agenda is not affiliated with "Mean Docker" Project. README Source: nitin27may/mean-docker

Open Source Agenda Badge

Open Source Agenda Rating