AWS EC2 HOSTING NODE JS WEBSITE WITH DYNAMODB AND CI CD WITH JENKINS
In this article, we’ll build a simple Node.js registration and login website that’s hosted on AWS EC2 with AWS DynamoDB as the database. Additionally, utilising Jenkins as a CI/CD devops tool and GitHub as a source code management tool, we will integrate the continuous integration and continuous deployment of the website from the source code to the hosted website.
ARCHITECTURE OF THE PROJECT
Below image is the architecture of the project we are going to build
STEPS FOR PROJECT
- Create a Node.Js Website
- Integrate AWS DynamoDB with website
- Host it on AWS EC2
- Setting up Jenkins on AWS EC2
- Creating Pipeline
STEP -1 CREATE NODE.JS WEBSITE
In this first step, a node js website has been built, with app.js as the primary javascript file and other html files being stored in views. The github link contains the website’s source code.
An overview of the website is provided below.
Our website is on port 9090.
LOGIN PAGE
REGSITER PAGE
STEP -2 INTEGRATE IT WITH AWS DYNAMODB
We must use the AWS SDK in order to link Dynamo DB with our Node JS source code.
Download aws-sdk using npm
npm install aws-sdk
We need Aws access key to access AWS resources through our code.
Path :: IAM -> Users -> User_name ->Security Credentials -> Access Keys
NOTE — Per account you can have only two access keys
Now, Create access key and select the Application running outside the AWS option as shown in below figure.
Add Description and then create the access key.
Download your key.
NOTE- Don’t share your key with anyone and on github
Back to our Node.js code we need to add the given code with your access keys and secret key to access dynamodb from our code.
const { DynamoDB } = require("@aws-sdk/client-dynamodb");
const dynamodb = new DynamoDB({
region: "ap-south-1",
credentials: {
accessKeyId: "*****",
secretAccessKey: "*****",
},
});
Now create DynamoDb table using TERRAFORM.
provider "aws" {
region = "ap-south-1"
accessKeyId: "*****"
secretAccessKey: "*****"
}
resource "aws_dynamodb_table" "users" {
name = "users"
billing_mode = "PAY_PER_REQUEST"
hash_key = "email"
attribute {
name = "email"
type = "S"
}
global_secondary_index {
name = "email-index"
hash_key = "email"
projection_type = "INCLUDE"
read_capacity = 5
write_capacity = 5
non_key_attributes = ["name", "password"]
}
}
Save the above code as main.tf
Run the below command to run the terraform file :-
terraform init
terraform plan
terraform apply
Now the table must had been created in AWS , you can check it using your AWS console.
Now adding the register function code of the Node.js app.js file.
app.post("/auth_register", (req, res) => {
let register_data = {
name: req.body.name,
email: req.body.email,
password: req.body.password,
};
const params = {
TableName: "users",
Item: {
name: { S: register_data.name },
email: { S: register_data.email },
password: { S: register_data.password },
},
};
const checkParams = {
TableName: "users",
Key: {
email: { S: register_data.email },
},
};
dynamodb.getItem(checkParams, function (err, data) {
if (err) {
console.log("Error checking if email already exists:", err);
} else if (data.Item) {
console.log("Email already registered:", data);
res.render("register_error.ejs", {
message: "This email address is already registered.",
});
} else {
dynamodb.putItem(params, function (err, data) {
if (err) {
console.log("Error adding item to table:", err);
} else {
console.log("Item added to table:", data);
res.render("register_success.ejs");
}
});
}
});
});
Now adding the login function code of the Node.js app.js file.
app.post("/auth_login", (req, res) => {
//post function to authorize user login
let email = req.body.email, //declare email/password variable
password = req.body.password;
const params = {
TableName: "users",
Key: {
email: { S: email },
},
ProjectionExpression: "password",
};
dynamodb.getItem(params, (err, data) => {
if (err) {
console.log(err);
res.render("login.ejs", { error: "User not found" });
} else {
if (
!data.Item ||
!data.Item.password ||
password !== data.Item.password.S
) {
res.render("login.ejs", { error: "Invalid email or password" });
} else {
res.render("homepage.ejs");
}
}
});
});
Hence the DynamoDb is successfully integrated with the Node.JS application.
IMP :: Create a github repo and push all this code in it . Remeber to remove your security credentials.
STEP 3 Host it on AWS EC2
We will now create an AWS EC2 ubuntu instance and will download node js and host our application on it.
Create an Ec2 like the configuration in the given image.
You need to change the security groups inbound rules because we have our website hosting on 9090 port and further we want jenkins on 8080 port so we need to add custom tcp for both of these port.
Connect this to your local machine using putty and ubuntu as user name and your ppk file.
Run the below commands to download the node js on your instance.
sudo apt update
sudo apt upgrade
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - &&\
sudo apt-get install -y nodejs
Now download git using below command.
sudo apt-get install git
Check whether it is downloaded or not using below command.
node --version
git --version
Now clone the github repo of your website on the AWS EC2 with the given command.
git clone <REPO-NAME>
Now run your app.js and check on <public-ip-of-instance>:9090 your website will be hosted successfully.
STEP 4 Setting up Jenkins on AWS EC2
To create a pipeline we neek jenkins on our instance so lets download jenkins.
We may need to be root user to access jenkins . So error occur run sudo su command.
Commands to download jenkins.
For jenkins we need jdk-11 on our instance, so let’s first download java development kit.
sudo apt install openjdk-11-jdk -y
java -version
Downloading jenkins commands.
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null
sudo apt update
sudo apt install jenkins -y
Checking on <public-ip-of-instance>:8080 showing the jenkins dashboard or not.
After that put admin password from the file location given and then create your user on jenkins.
Below given is the given dashboard of jenkins after all set up.
STEP 5 Creating Pipeline
Now create a freestyle project by clicking on new item on the left side of the jenkins dashboard.
Add the description
Now in the Source Code Management choose git and add the github repository
In build triggers check poll scm and add * * * * * in schedule.These means that pipeline will build every time their is a changes in github and will check the github repo in every minutes for the changes.
In the build steps select execute shell and put the below given code.
git fetch <Github- Repo-Link>
git merge origin/master
npm install
Leave the rest of it as it is and save the pipeline.
Now go to the jenkins workspace which is /var/lib/jenkins/workspace/. It will contain the folder with the name of your pipeline and you can see the changes that are pushed in github is automatically integrated with this folder.
Remember to add the access key in the folder as we had removed the key before pushing the code to Github.
Now to run our application after the terminal is closed we will use PM2.
Download pm2 using npm.
npm install pm2 -g
Start app using pm2.
sudo pm2 start app.js
sudo pm2 startup
Hurray!!!! Now our web is always running on port 9090.