Serverless MEAN Stack Application on MongoDB Atlas and Cloud Run

1. Introduction

In this post,we're going to see how Cloud Run and MongoDB come together to enable a completely serverless MEAN stack application development experience. We'll learn how to build a serverless MEAN application with Cloud Run and MongoDB Atlas, the multi-cloud application data platform by MongoDB.

What is Cloud Run?

Cloud Run enables you to build and deploy scalable containerized apps written in any language (including Go, Python, Java, Node.js, .NET, and Ruby) on a fully managed platform. Cloud Run stands out of the league by enabling us to:

  • Package code in multiple stateless containers that are request-aware and invoke it via HTTP requests
  • Only be charged for the exact resources you use
  • Support any programming language or any operating system library of your choice, or any binary

Check this link for more features in full context.

Serverless database with MongoDB Atlas

MongoDB launched serverless instances, a new fully managed, serverless database deployment in Atlas to solve this problem. With serverless instances you never have to think about infrastructure — simply deploy your database and it will scale up and down seamlessly based on demand — requiring no hands-on management. And the best part, you will only be charged for the operations you run. To make our architecture truly serverless, we'll combine Cloud Run and MongoDB Atlas capabilities.

MEAN Stack

The MEAN stack is a technology stack for building full-stack web applications entirely with JavaScript and JSON. The MEAN stack is composed of four main components—MongoDB, Express, Angular, and Node.js.

  • MongoDB is responsible for data storage.
  • Express.js is a Node.js web application framework for building APIs.
  • Angular is a client-side JavaScript platform.
  • Node.js is a server-side JavaScript runtime environment. The server uses the MongoDB Node.js driver to connect to the database and retrieve and store data.

What you'll build

You'll write a full stack Employee-Job Role application in MongoDB, Express JS, Angular JS and Node JS. It contains:

  • A server application in Node JS and Express JS, containerized
  • A client application build in AngularJS, containerized
  • Both applications are deployed in Cloud Run
  • Server app connects toServerless MongoDB instance using MongoDB NodeJS driver
  • Server API carries out the read-write interactions with database
  • Client application is the user interface for the Employee-Job Role application

What you'll learn

  • How to create a serverless MongoDB Instances
  • How to set up a Cloud Run project
  • How to deploy web applications in Google Cloud Run
  • How to create and deploy a MEAN Stack Application

2. Requirements

  • A browser, such as Chrome or Firefox
  • A Google Cloud Platform project that contains your Cloud Run and MongoDB Atlas instance
  • The next section has the list of steps to create the MEAN Stack application

3. Create the MongoDB Serverless instance and database

e5cc775a49f2fb0.png

  • Once you sign up, click the "Build a Database" button to create a new serverless instance. Select the following configuration:

fca10bf6f031af7a.png

  • Once your serverless instance is provisioned, you should see it up and running

d13c4b8bdd9569fd.png

  • Click on the "Connect" button to add a connection IP address and a database user
  • For this codelab, we'll use the "Allow Access from Anywhere" setting. MongoDB Atlas comes with a set of security and access features. You can learn more about them in the security features documentation article
  • Use credentials of your choice for the database username and password. Once these steps are complete, you should see the following:

bffeef16de1d1cd2.png

  • Proceed by clicking on the "Choose a connection method" button and then selecting "Connect your application"

75771e64427acd5e.png

  • Copy the connection string you see and replace the password with your own. We'll use that string to connect to our database in the following sections

4. Set up a Cloud Run Project

  • First, sign in to Cloud Console, create a new project, or reuse an existing one
  • Remember the Project Id for the project you created
  • Below is an image that shows the new project page, where you can see your project id as you create it

f32dbd4eb2b7501e.png

  • Then, enable Cloud Run API from Cloud Shell:
  • Activate Cloud Shell from the Cloud Console. Simply click Activate Cloud Shell
  • Once connected to Cloud Shell, you should see that you are already authenticated and that the project is already set to your PROJECT ID. If, for some reason, the project is not set, simply issue the following command:
gcloud config set project PROJECT_ID

3da173210a016316.png

  • Use the below command:
gcloud services enable run.googleapis.com
  • We will be using Cloud Shell and Cloud Shell Editor for code references. To access Cloud Shell Editor, click Open Editor from the Cloud Shell Terminal:

83793a577f08e4d4.png

5. Clone MEAN Stack Project

  • We'll deploy an employee management web application. The REST API is built with Express and Node.js; the web interface, with Angular; and the data will be stored in the MongoDB Atlas instance we created earlier
  • Clone the project repository by executing the following command in the Cloud Shell Terminal:
git clone https://github.com/mongodb-developer/mean-stack-example.git

6. Deploy the Express and Node.js REST API

Docker Configuration File

  • First, we'll deploy a Cloud Run service for the Express REST API. The most important file for our deployment is the Docker configuration file. Let's take a look at it:

mean-stack-example/server/Dockerfile

# Use the official lightweight Node.js 12 image.
# https://hub.docker.com/_/node
FROM node:17-slim
 
WORKDIR /usr/app
COPY ./ /usr/app
 
# Install dependencies and build the project.
RUN npm install
RUN npm run build
 
# Run the web service on container startup.
CMD ["node", "dist/server.js"]
  • The configuration sets up Node.js, and copies and builds the project. When the container starts, the below command starts the service
node dist/server.js
  • To start a new Cloud Run deployment, click on the Cloud Run icon on the left sidebar:

48c73bda3aa4ea02.png

  • Then, click on the Deploy to Cloud Run icon:

cde124ba8ec23b34.png

  • Fill in the service configuration as follows:
  • Service name: node-express-api
  • Deployment platform: Cloud Run (fully managed)
  • Region: Select a region close to your database region to reduce latency
  • Authentication: Allow unauthenticated invocations
  • Under Revision Settings, click on Show Advanced Settings to expand them:
  • Container port: 5200
  • Environment variables. Add the following key-value pair and make sure you add the connection string for your own MongoDB Atlas deployment:
ATLAS_URI:mongodb+srv:/<username>:<password>@sandbox.pv0l7.mongodb.net/meanStackExample?retryWrites=true&w=majority
  • For the Build environment, select Cloud Build
  • Finally, in the Build Settings section, select:
  • Builder: Docker
  • Docker: mean-stack-example/server/Dockerfile
  • Click the Deploy button and then Show Detailed Logs to follow the deployment of your first Cloud Run service!
  • After the build has completed, you should see the URL of the deployed service:

759c69ba52a85b10.png

  • Open the URL and append ‘/employees' to the end
  • You should see an empty array because currently, there are no documents in the database.

Let's deploy the user interface so we can add some!

7. Deploy the Angular Web Application

Our Angular application is in the client directory. To deploy it, we'll use the Nginx server and Docker. Just a thought, there is also an option to use Firebase Hosting for your Angular application deployment as you can serve your content to a CDN (content delivery network) directly.

Configuration Files

Let's take a look at the configuration files:

mean-stack-example/client/nginx.conf

events{}
 
http {
   include /etc/nginx/mime.types;
   server {
       listen 8080;
       server_name 0.0.0.0;
       root /usr/share/nginx/html;
       index index.html;
 
       location / {
           try_files $uri $uri/ /index.html;
       }
   }
}
  • In the Nginx configuration, we specify the default port—8080, and the starting file—index.html

mean-stack-example/client/Dockerfile

FROM node:17-slim AS build
 
WORKDIR /usr/src/app
COPY package.json package-lock.json ./
 
# Install dependencies and copy them to the container
RUN npm install
COPY . .
 
# Build the Angular application for production
RUN npm run build --prod
 
# Configure the nginx web server
FROM nginx:1.17.1-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /usr/src/app/dist/client /usr/share/nginx/html
 
# Run the web service on container startup.
CMD ["nginx", "-g", "daemon off;"]
  • In the Docker configuration, we install Node.js dependencies and build the project. Then, we copy the built files to the container, configure, and start the Nginx service
  • Finally, we need to configure the URL to the REST API so that our client application can send requests to it. Since we're only using the URL in a single file in the project, we'll hardcode the URL. Alternatively, you can attach the environment variable to the window object and access it from there.

mean-stack-example/client/src/app/employee.service.ts

...
@Injectable({
 providedIn: 'root'
})
export class EmployeeService {
 // Replace with the URL of your REST API
 private url = 'https://node-express-api-vsktparjta-uc.a.run.app'; 
...
  • We're ready to deploy to Cloud Run! Start a new deployment with the following configuration settings:
      - Service Settings: Create a service
    
  • Service name: angular-web-app
  • Deployment platform: Cloud Run (fully managed)
  • Authentication: Allow unauthenticated invocations
  • For the Build environment, select Cloud Build
  • Finally, in the Build Settings section, select:
  • Builder: Docker
  • Docker: mean-stack-example/client/Dockerfile
  • Click that Deploy button again and watch the logs as your app is shipped to the cloud! When the deployment is complete, you should see the URL for the client app

5da1d7defc1082fc.png

  • Open the URL, and play with your application!

db154f1cd57e38f0.png

8. Clean up

To avoid incurring charges to your Google Cloud account for the resources used in this post, follow these steps.

Terminate MongoDB instances

  1. Go to the MongoDB Instance clusters
  2. Select the cluster, instance you created
  3. Click the ellipses next to the cluster name and select Terminate from the list

Delete the Cloud Run Deployments

  1. Go to the Cloud Run page in the Google Cloud Console
  2. Select the Cloud Run service you want to delete
  3. Click the delete icon on top of the console

9. Congratulations

Congratulations, you've successfully created MEAN Stack Web Application on Cloud Run!