In this project, you will build a serverless web application using AWS Lambda, DynamoDB, and S3. The application will allow users to create, read, update, and delete (CRUD) items from a DynamoDB table.
- Create a DynamoDB table to store the items
- Build a Lambda function to handle the CRUD operations on the DynamoDB table
- Use S3 to store and host the web application's static files (HTML, CSS, and JavaScript)
- Create a CloudFront distribution to serve the S3-hosted static files with low latency
First, you need to create an Amazon S3 bucket where you will store your objects.
- Sign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/
- In the navigation bar on the top of the page, choose the name of the currently displayed AWS Region. Next, choose the Region in which you want to create a bucket.
- In the left navigation pane, choose Buckets.
- Choose Create bucket.
- Under General configuration, view the AWS Region where your bucket will be created.
- Under Bucket type, choose General purpose.
- For Bucket name, enter a name for your bucket, i will name it
jmwebapp
- Scroll down and leave everything else as default and Choose Create bucket.
You've created a bucket in Amazon S3.
After creating a bucket in Amazon S3, you're ready to upload an object to the bucket. An object can be any kind of file: a text file, a photo, a video, and so on.
- In the Buckets list, choose the name of the bucket that you want to upload your object to.
- On the Objects tab for your bucket, choose Upload.
-
Under Files and folders, choose Add files.
-
Choose a file to upload, we are going to upload the code provided in this GitHub repo, file name:
index.html
script.js
style.css
, and then choose Open, and choose Upload.
You've successfully uploaded an object to your bucket.
CloudFront delivers your content through a worldwide network of data centers called edge locations. When a user requests content that you're serving with CloudFront, the request is routed to the edge location that provides the lowest latency (time delay), so that content is delivered with the best possible performance.
To create a distribution:
- On Console and open the CloudFront console at https://console.aws.amazon.com/cloudfront/v4/home.
- In the navigation pane, choose Distributions, then choose Create distribution.
- The origin domain is the DNS domain name of the Amazon S3 bucket or HTTP server from which you want CloudFront to get objects for this origin, for example: Amazon S3 bucket – DOC-EXAMPLE-BUCKET.s3.us-west-2.amazonaws.com
We've created an S3 bucket earlier called jmwebapp
. Our origin domain is going to be jmwebapp.s3.us-east-1.amazonaws.com
- Origin path is optional, we will keep that as default.
- Choose Origin access control settings (recommended) if you want to make it possible to restrict access to an Amazon S3 bucket origin to only specific CloudFront distributions.
Choose Public if the Amazon S3 bucket origin is publicly accessible.
- Create a Origin Access Control - OAC
- You can use AWS WAF to protect your CloudFront distributions and origin servers. AWS WAF is a web application firewall that helps secure your web applications and APIs by blocking requests before they reach your servers.
But for the sake of this tutorial, we'll keep it simple and not use AWS WAF, choose "Do not use security protection"
-
After CloudFront creates your distribution, the value of the
Status
column for your distribution will change fromDeploying
to the date and time that the distribution is deployed. If you chose to enable the distribution, it will be ready to process requests at this time. -
Scroll down, leave everything else as default, and click "Create distribution"
- When your distribution is deployed, confirm that you can access your content using your new CloudFront URL or CNAME. For more information, see Testing a distribution.
Next, you need to copy the S3 Bucket policy, which you need to attach to your bucket so that the CloudFront can access your AWS S3 bucket:
- Back to the your distribution, click on Origin Tab, elect the origin name that you have created just and click on "Edit"
- Scroll down until you see the CloudFront permission policy statement, just click on you know "Copy policy" button and the policy will be copied to your clipboard, you need to paste this in your Amazon S3 bucket.
- Go back to your S3 Bucket and select the bucket where you have you know stored everything.
- Go to permission Tab, under permission you will see "Bucket policy", select that and click "Edit"
- Then you paste the content that you have you know copied. Basically the policy code is just allowing cloudfront service principle to access your S3 bucket, then click "Save changes"
- On the distribution console, we need to change the default root object to
index.html
because our AWS bucket contains a file called index.html and that is the entry point for our web application.
- The default root object is the oject (file name) to return when a viewer requests the URL (/) instead of a specific oject.
After you make the changes, make sure that it is deployed successfully.
We need to setup AWS Route 53, you need to have valid domain name. You can purchase one either from AWS Route 53 or other hositng provider.
I have a domain name julienmuke.cloud
form Hostinger (https://www.hostinger.com/)
- Let's Create Hosted Zone
A hosted Zone one tells Route 53 how to respond to DNS queries for a domain such as example.com or julienmuke.cloud.
- Back to your console navigate to AWS Route 53, choose Hosted zones in the navigation pane
- In the Create Hosted Zone pane, enter the name of the domain that you want to route traffic for, i'll use
julienmuke.cloud
. - For Type, accept the default value of Public Hosted Zone (if its VPC only then you can select private hosted Zone).
- As you can see the NS and SOA record will be created.
- The next thing that you need to do is copy these name servers (Route traffic) and you need to add it in your Hosting domain
- Navigate to your Cpanel, search for "Manage domain" or something similar to that, then change the "DNS/Nameservers" paste the name servers from AWS Route 53 Hosted Zones.
- Edit CloudFront settings - by using custom URLs by adding alternate domain names.
When you create a distribution, CloudFront provides a domain name for it, such as d111111abcdef8.cloudfront.net. Instead of using this provided domain name, you can use an alternate domain name (also known as a CNAME).
Let see how to use your own domain name, such as www.example.com:
- Back to your CloudFront console, choose the ID for the distribution that you want to update.
- On the General tab, choose Edit.
- Update the following values:
Alternate Domain Names (CNAMEs)
Add your alternate domain names, i'll use a sub-domain greeting.julienmuke.cloud
separate domain names with commas, or type each domain name on a new line.
- Get an SSL/TLS certificate from an authorized certificate authority (CA) that covers the domain name. Add the certificate to your distribution to validate that you are authorized to use the domain.
- Choose "Request a public certificate" request a public SSL/TLS certificate from Amazon. By default, public certicates are trusted by browsers and operating systems.
- Next you need to provide a fully qualified domain name
*.julienmuke.cloud
- Leave everything else as default and click "Request"
NOTE: You have to wait a few minutes for the certificate to be issued.
- Next, to verify the SSL certificatethe, we need to select our new certificatethe we've created, complete the CloudFront settings and click "Save changes"
- Let create new record to validate the SSL/TLS certificate from Amazon.
- Go to your AWS Certificate Manager (ACM) and click on "Create record in route 53"
- It is going to create a CNAME record in Route 53, then click on "Create record"
- Next, let create another record for our subdomain
greeting.julienmuke.cloud
- Click on "Create record"
- The record name is
greeting
.julienmuke.cloud - Enable "Alias"
- Choose route traffic: "Alias to CloudFront distribution"
- Choose the distribution listed, it will show the CloudFront with the SSL certificate that we configured.
- Click "Create records"
What happens is that the routing will be made and the records will be created for greeting.julienmuke.cloud
After you complete the CloudFront configuration, you will be able to access your website using greeting.julienmuke.cloud
copy the URL and paste it on your web browser
- Below is the Live website with a simple functionality, you enter your full name, click "Submit" button and it will display you full name which is stored in the S3 Bucket.
As you can see the website is working and the SSL Certificate is enabled.
The next step is to create a DynamoDB and add views functionality on our webpage using a Lambda.
Feature: We have our static website, whenever someone is visiting the website the [ Views: ] counter will inscrease.
To create a DynamoDB Table:
- Nagivate to your AWS Management Console and open the DynamoDB console
- Choose Create table
- Enter the Table details as follows:
* For Table name, enterserverless-web-application-on-aws
* For Partition key, enterid
- For Table settings, keep the default selection of Default settings.
- Choose Create table to create the table.
- Once the DynamoDB Table is created, click on the table name, and then click "Explore table items"
- Choose "Create item"
- You can add, remove, or edit attributes of an item:
* For id partition key, enter0
* Click "Add new attributes" and choose "Number"
* For attribute name, enterviews
* For value, enter1
AWS Identity and Access Management (IAM) is a web service that helps you securely control access to AWS resources for your users. You use IAM to control who can use your AWS resources (authentication) and what resources they can use and in what ways (authorization).
To create an IAM role:
- Go to the IAM Management Console, click Roles in the left nav pane, then click "Create role"
- Select type of trusted entity as
AWS service
- For servise or use case, select
lambda
then click "Next"
- The Create role Attach permissions policies page opens with options for creating a new policy, refreshing the page, and searching existing policies named
AmazonDynamoDBFullAccess
and click "Next"
- For the role name, enter
serverless-web-application-on-aws
- Scroll and click "Create role"
To create a Lambda function with the console:
- Open the Functions page of the Lambda console
- Choose Create function
- Select Author from scratch
- In the Basic information pane, for Function name enter
serverless-web-application-on-aws
- For Runtime, choose Python 3.8
- Click on Advance settings, and select "Enable function URL" (This is to use function URLs to assign HTTP endpoints to your Lambda function).
- For Auth type select "None" You are allowing Lambda won't perform IIM authentication on request to your function URL basically the URL endpoint will be public.
- Select Cross Origin Ratio Sharing (CORS) so that only the website that starts with
julienmuke.cloud
can access this particular Lambda function. - Leave architecture set to x86_64 and choose "Create function"
- Modify the code in the console:
* Choose the Code tab: In the console's built-in code editor, you should see the function code that Lambda created. If you don't see the lambda_function.py tab in the code editor, select lambda_function.py in the file explorer as shown on the image below.
* Paste the following code into the lambda_function.py tab, replacing the code that Lambda created.
* Then click "Deploy"
import json
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('serverless-web-application-on-aws')
def lambda_handler(event, context):
response = table.get_item(Key={
'id':'0'
})
views = response['Item']['views']
views = views + 1
print(views)
response = table.put_item(Item={
'id':'0',
'views': views
})
return views
- Next, we've created an IAM role, now let's attache the IAM role to this Lambda function.
* Select the permission tab
* Click "Edit"
- Srolll down to "Execution role" and select the lambda function we've created and click "Save"
- Let test our lambda function:
* Click "Deploy" and then "Test"
* For configure test event, enterTestEvent
and click "Save"
* The response will update to 2 and
If you check our DynamoDB table and refesh the table, the value of views will update to 2 as well.
- Next, we will edit the script.js file so that the views counter will display on the webpage, to do that:
- Create a script.js file, open it in code editor of your choice (VS Code) copy and paste the code below:
const form = document.querySelector('form');
const greeting = document.querySelector('#greeting');
form.addEventListener('submit', (event) => {
event.preventDefault();
const name = document.querySelector('#name').value;
greeting.textContent = `Hello, ${name}!`;
});
const counter = document.querySelector(".counter-number");
async function updateCounter() {
let response = await fetch(
"YOUR-FUNCTION-URL"
);
let data = await response.json();
counter.innerHTML = `Views: ${data}`;
}
updateCounter();
- Go to your Lambda function, copy your function URL
- Paste the ULR to the JavaScript counter-number
as shown in image below:
- Next, save the changes, now you need the upload the script.js file once again into your S3 Bucket (see step 1.2 above)
NOTE: it will take time to process, be patient and take a pause and come back later to test the application.
🏆 As you can see below, the views counter will increase everytime you refresh the page, it will also increase in your DynamoDB table.
All services used are eligible for the AWS Free Tier. However, charges will incur at some point so it's recommended that you shut down resources after completing this tutorial.