AWS/CDK

Host a static website on S3 using AWS CDK

brightlightkim 2022. 9. 24. 04:41

If you’ve built a website, whether for personal or commercial use, you probably researched web hosting options. Lots of companies provide this kind of services. In this post, we will build a very simple website, and host it on Amazon S3 (Amazon storage service), which can be used to host a static website (a site that contains static content and client-side scripts).

The interesting part is that we will use AWS CDK to define the infrastructure we’re using. I’ve learned about this a couple of weeks ago, and thought to document my learnings through a blog post.

Below are a few definitions to get us started:

Amazon S3: Object storage service that offers scalability, security, data availability and performance. We will store our website code in a bucket on S3; think of a bucket as a folder (in reality a bucket is not a folder, but visualizing it this way serves our purpose).

AWS CDK: AWS Cloud Development Kit; it’s a software development framework that enables defining infrastructure in code.

Pre-requisites

  • Create an AWS account. If you’re new to AWS services and want to explore, I highly recommend setting up a billing alarm so that you avoid any unnecessary charges.
  • Install NodeJS and npm — https://nodejs.org/en/ — npm is installed automatically with NodeJS
  • Install Typescript: npm i -g typescript
  • Install the AWS command line interface
  • Configure AWS client: aws configure; you will be asked for access key ID, secret access key and aws region (details can be found here)
  • Install the AWS CDK globally: npm install -g aws-cdk

Implementation

  • Create a new folder that will contain our site and infrastructure code: mkdir static-site-s3
  • Inside this folder create 2 folders, one for the “hello world” website and one for the infrastructure: cd static-site-s3 & mkdir website infrastructure
  • Navigate to the website folder and create a new file “index.html”: `cd website & touch index.html, with the following content:
<!DOCTYPE html> <html>  <head>   <title>Hello world</title>  </head> <body>  <h1>My S3 hosted website</h1> </body></html>
  • Navigate back to the infrastructure folder: cd ../infrastructure
  • Initialize the infrastructure code: cdk init app --language typescript. This will generate the boilerplate code for us
  • Have a look at “cdk.json”, it contains the following command npx ts-node bin/infrastructure.ts ,which will run the AWS CDK app — no change is needed here
  • Open the “bin/infrastructure.ts” file, which is the entry point to our stack; add the “AWS region” to that file:
#!/usr/bin/env nodeimport 'source-map-support/register';import * as cdk from '@aws-cdk/core';import { InfrastructureStack } from '../lib/infrastructure-stack';const app = new cdk.App();new InfrastructureStack(app, 'InfrastructureStack', { env: {  region: 'ap-southeast-2', },});
  • Now open “lib/infrastructure-stack.ts”, which will contain the definition for our stack

Define the stack

  • You would need to install “@aws-cdk/aws-s3” dependency in order to use create an S3 resource (a bucket in this case): npm i @aws-cdk/aws-s3, and import it at the top of the “lib/infrastructure-stack.ts” file: import * as s3 from '@aws-cdk/aws-s3'
  • The “lib/infrastructure-stack.ts” file contains the following comment: “ // The code that defines your stack goes here”, under this comment add the following:
const myBucket = new s3.Bucket(this, "my-static-website-bucket", {
   publicReadAccess: true,
   removalPolicy: cdk.RemovalPolicy.DESTROY,        
   websiteIndexDocument: "index.html"
});
  • In the previous code snippet we also defined some options for our S3 bucket, such as the public read access, the removal policy, where in our case destroy the bucket, and the website index document…
  • Note that the bucket name has to be unique — replace “my-static-website-bucket” with a unique name of your choice
  • Next we will define the deployment. You would need to install “@aws-cdk/aws-s3-deployment” dependency in order to use create an S3 deployment resource: npm i @aws-cdk/aws-s3-deployment, and import it at the top of the “lib/infrastructure-stack.ts” file: import * as s3Deployment from '@aws-cdk/aws-s3-deployment':
const deployment = new s3Deployment.BucketDeployment(this, "deployStaticWebsite", {
   sources: [s3Deployment.Source.asset("../website")],
   destinationBucket: myBucket
});
  • The previous snippet is what will deploy our code to the S3 bucket — notice the “sources” option pointing to our website code

Deployment

Now we will deploy this stack to AWS:

  • In your terminal run: cdk bootstrap. Notice the “cdk-out” folder that got generated, which include our website code (index.html)

The first time you deploy an AWS CDK app into an environment (account/region), you’ll need to install a “bootstrap stack”. This stack includes resources that are needed for the toolkit’s operation. For example, the stack includes an S3 bucket that is used to store templates and assets during the deployment process.

  • Run cdk synth, which synthesizes (produce) the CloudFormation template for the stack in our app
  • run cdk deploy
  • Enter “y” to continue with the deployment

Once done, open your AWS console, then navigate to the cloud formation page. Notice the following:

  • There is a CDKToolkit stack with the following description: The CDK Toolkit Stack. It was created by `cdk bootstrap` and manages resources necessary for managing your Cloud Applications with AWS CDK.
  • There is an InfrastructureStack stack

In the AWS console, open S3. Notice the bucket created with a name similar to infrastructurestack-mystaticwebsite…

  • Open the bucket, you will find the index.html. Click it
  • At the bottom of the page you will find an “Object URL”, click it
  • This will open the static website we’ve created showing a title of “Hello world” and a content “My S3 hosted website”

NOTE: It is possible that the resources created might incur costs. Make sure to delete the S3 bucket and the cloudformation stacks to avoid any costs.

Running cdk destroy would clean everything, but would fail to delete the S3 bucket as it is not empty (https://github.com/aws/aws-cdk/issues/3297)

You can find the code at the following github repository: https://github.com/AHaydar/static-site-s3

I hope this was helpful. Please let me know your feedback.