Introduction
In this tutorial, we will walk through the process of creating a blog application(Backend) using Node.js, Express, and MongoDB, and then deploying it to an AWS EC2 instance. This guide is perfect for developers looking to build a full-stack application and learn about deploying to a cloud service.
Prerequisites
- Basic knowledge of JavaScript and Node.js
- An AWS account
- Node.js and npm installed on your machine
- Access to MongoDB Atlas
Step 1: Setting Up Your Node.js Project
First, create a new directory for your project and navigate into it:
mkdir blog-app cd blog-app
Initialize a new Node.js project:
npm init -y
Create the main server file:
mkdir api touch app.js
Step 2: Setting Up Database
Go over to https://account.mongodb.com/account/login and login, and a create a project for your app.
Give a name to your project and create it.
Now create a cluster as per your needs, here I am choosing a free option i.e. M0
Now we have to create a database user and get the mongodb url to access it on our node app.
Choose Drivers option in Connect to your application
copy the url string and paste it in your node app env files.
//.env MONGO_URI=mongodb+srv://testuser01:test@123@cluster0.njocipk.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0
Step 3: Setting Up Express
In your app.js file, set up a basic Express server:
// api/app.js const express = require('express'); const mongoose = require('mongoose'); const bodyParser = require('body-parser'); const dotenv = require('dotenv'); dotenv.config(); const app = express(); app.use(bodyParser.json()); // Connect to MongoDB mongoose.connect(process.env.MONGO_URI) .then(() => console.log('MongoDB connected')) .catch(err => console.log(err)); const PORT = process.env.PORT || 5000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); });
Step 4: Creating Models and Routes and Controllers
mkdir models touch models/blog.model.js
Define the Blog schema:
import mongoose from "mongoose"; const blogSchema = new mongoose.Schema( { content: { type: String, required: true, }, title: { type: String, required: true, unique: true, }, slug: { type: String, required: true, unique: true, }, thumbnail: { type: String, required: true, }, category: { type: String, required: true, }, isFeatured: { type: Boolean, default: false, }, summary: { type: String, required: true, }, }, { timestamps: true } ); const Blog = mongoose.model("Blog", blogSchema); export default Blog;
Next, create a folder called routes and add a blog.route.js file to handle your blog post routes:
import express from "express"; import { createBlog, getBlogs, updateBlog, } from "../controllers/blog.controller.js"; const router = express.Router(); router.post("/create", createBlog); router.get("/get/all", getBlogs); router.get("/get/:slug", getSingleBlog); router.put("/update/:slug", verifyToken, updateBlog); export default router;
Next, create a folder called controllers and add a blog.controller.js file to handle your blog functions:
import Blog from "../models/blog.model.js"; export const createBlog = async (req, res, next) => { if (!req.body.title || !req.body.content) { return next(errorHandler(400, "Please provide all required fields")); } const newBlog = new Blog(req.body); try { const savedBlog = await newBlog.save(); res.status(201).json(savedBlog); } catch (error) { next(error); } }; export const getBlogs = async (req, res, next) => { try { const allBlogs = await Blog.find({}); const dateDescBlogs = allBlogs.sort((a, b) => { return new Date(b.createdAt) - new Date(a.createdAt); }); res.status(201).json(dateDescBlogs); } catch (error) { next(error); } }; export const getSingleBlog = async (req, res, next) => { try { const singleBlog = await Blog.findOne({ slug: req.params.slug }); res.status(201).json(singleBlog); } catch (error) { next(error); } }; export const updateBlog = async (req, res, next) => { try { const updatedBlog = await Blog.findOneAndUpdate( { slug: req.params.slug }, { $set: { title: req.body.title, status: req.body.status, summary: req.body.summary, slug: req.body.slug, category: req.body.category, isFeatured: req.body.isFeatured, thumbnail: req.body.thumbnail, content: req.body.content, }, }, { new: true, } ); res.status(200).json(updatedBlog._doc); } catch (error) { next(error); } };
Add the routes to your app.js file, finally app.js will look like:
import dotenv from "dotenv"; import express from "express"; import mongoose from "mongoose"; import cors from "cors"; import bodyParser from "body-parser"; import blogRoutes from "./routes/blog.route.js"; dotenv.config(); // Connect to MongoDB mongoose.connect(process.env.MONGO_URI) .then(() => console.log('MongoDB connected')) .catch(err => console.log(err)); const app = express(); const PORT = 5000; app.use(express.json()); app.use(cors()); app.use(bodyParser.json()); app.listen(PORT, () => { console.log("Server is running on port", PORT); }); app.use("/api/blog", blogRoutes);
Step 5: Run the server
node api/app.js
Step 6: Access Your Blog Locally
Open a browser and navigate to http://localhost:5000 to see your blog posts.
Step 7: Deploying to AWS EC2
1. Launch an EC2 Instance
- Go to the AWS Management Console.
- Navigate to EC2 and launch a new instance.
- Choose an Amazon Machine Image (AMI) like Ubuntu.
- Select an instance type, such as t2.micro (which is free tier eligible).
- Configure instance details and add storage as needed.
- Add a security group rule to allow HTTP and SSH access.
- Review and launch the instance.
2. Connect to Your EC2 Instance
Once your instance is running, connect to it using SSH:
ssh -i path/to/your-key.pem ubuntu@your-ec2-public-ip
3. Set Up Your Environment
Update your package list and install Node.js and npm:
sudo apt update sudo apt install nodejs npm
4. Deploy Your Application
Clone your project repository from GitHub (or upload your files directly):
git clone https://github.com/yourusername/your-repo.git cd your-repo
Install your project dependencies:
npm install
Set up your environment variables. Create a .env file and add your MongoDB URI:
touch .env nano .env
Add the following to your .env file:
MONGO_URI=mongodb+srv://testuser01:test@123@cluster0.njocipk.mongodb.net/?retryWrites=true&w=majority&appName=Cluster0
Step 8: Access Your Blog Online
Open a browser and navigate to http://your-ec2-public-ip:5000/posts to see your blog posts.
Conclusion
By following these steps, you have created a full-stack blog application using Node.js, Express, and MongoDB, and deployed it to an AWS EC2 instance. This setup allows you to manage and deploy your application efficiently, leveraging the power of cloud computing.