このハンズオンでは、AWS CDKを使って、S3 + CloudFrontで静的Webサイト(HTML/CSS/画像)をホスティングする環境を構築します。
CloudWatchでアクセスログの監視も設定します。
Positive : AWS CDKを使うことで、インフラをコードで管理できます。再現性が高く、環境の複製も容易です。
Negative : 本ハンズオンで作成するリソースには料金が発生する場合があります。ハンズオン終了後は必ずリソースを削除してください。
Positive : GitHub Codespaces にはNode.js / Git がプリインストールされています。このハンズオンで使用するAWS CDKもCodespaces上で利用可能です。
Codespace のターミナルで以下のコマンドを実行します。
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" unzip awscliv2.zip sudo ./aws/install rm -rf awscliv2.zip aws/ aws --version
aws configure
項目 | 値 |
AWS Access Key ID | 管理者から払い出されたキー |
AWS Secret Access Key | 管理者から払い出されたシークレット |
Default region name |
|
Default output format |
|
aws sts get-caller-identity
Negative : アクセスキーをGitリポジトリにコミットしないよう注意してください。
AWS CDKをグローバルにインストールします。
npm install -g aws-cdk cdk --version
プロジェクトディレクトリを作成し、CDKプロジェクトを初期化します。
mkdir handson-static-hosting cd handson-static-hosting cdk init app --language typescript
Positive : cdk init コマンドにより、TypeScriptベースのCDKプロジェクトが自動生成されます。
以下のようなディレクトリ構成が生成されます。
handson-static-hosting/
├── bin/
│ └── handson-static-hosting.ts
├── lib/
│ └── handson-static-hosting-stack.ts
├── website/ ← ★ これから作成
│ ├── index.html
│ ├── style.css
│ └── images/
├── cdk.json
├── package.json
└── tsconfig.json
mkdir -p website/images
website/index.html を以下の内容で作成します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AWS サーバレスハンズオン</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<nav>
<h1>☁️ AWS Serverless Handson</h1>
</nav>
</header>
<main>
<section class="hero">
<h2>サーバレスで始めるWebホスティング</h2>
<p>S3 + CloudFrontで高速・低コストなWebサイトを構築しよう</p>
</section>
<section class="features">
<div class="feature-card">
<h3>🚀 高速配信</h3>
<p>CloudFrontのCDNで世界中に高速配信</p>
</div>
<div class="feature-card">
<h3>💰 低コスト</h3>
<p>サーバレスだから使った分だけ課金</p>
</div>
<div class="feature-card">
<h3>🔒 セキュア</h3>
<p>HTTPS対応で安全に配信</p>
</div>
</section>
</main>
<footer>
<p>© 2026 AWS Handson. All rights reserved.</p>
</footer>
</body>
</html>
website/style.css を以下の内容で作成します。
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #0a0a2e 0%, #1a1a4e 100%);
color: #ffffff;
min-height: 100vh;
}
header nav {
display: flex;
justify-content: center;
padding: 1.5rem 2rem;
background: rgba(255, 255, 255, 0.05);
backdrop-filter: blur(10px);
}
.hero {
text-align: center;
padding: 4rem 2rem;
}
.hero h2 {
font-size: 2.5rem;
margin-bottom: 1rem;
background: linear-gradient(90deg, #00d2ff, #7b2ff7);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.hero p {
font-size: 1.2rem;
color: #aaa;
}
.features {
display: flex;
justify-content: center;
gap: 2rem;
padding: 2rem;
flex-wrap: wrap;
}
.feature-card {
background: rgba(255, 255, 255, 0.08);
border-radius: 16px;
padding: 2rem;
width: 280px;
text-align: center;
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.1);
transition: transform 0.3s ease;
}
.feature-card:hover {
transform: translateY(-5px);
}
.feature-card h3 {
font-size: 1.5rem;
margin-bottom: 0.8rem;
}
.feature-card p {
color: #bbb;
}
footer {
text-align: center;
padding: 2rem;
color: #666;
margin-top: 3rem;
}
npm install aws-cdk-lib constructs
lib/handson-static-hosting-stack.ts を以下の内容に書き換えます。
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as cloudfront from 'aws-cdk-lib/aws-cloudfront';
import * as origins from 'aws-cdk-lib/aws-cloudfront-origins';
import * as s3deploy from 'aws-cdk-lib/aws-s3-deployment';
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import { Construct } from 'constructs';
export class HandsonStaticHostingStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// S3バケット(WebサイトホスティングはCloudFront経由のため不要)
const websiteBucket = new s3.Bucket(this, 'WebsiteBucket', {
bucketName: `handson-website-${this.account}`,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
});
// CloudFrontディストリビューション
const distribution = new cloudfront.Distribution(this, 'Distribution', {
defaultBehavior: {
origin: origins.S3BucketOrigin.withOriginAccessControl(websiteBucket),
viewerProtocolPolicy: cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
cachePolicy: cloudfront.CachePolicy.CACHING_OPTIMIZED,
},
defaultRootObject: 'index.html',
enableLogging: true,
});
// S3へのデプロイ
new s3deploy.BucketDeployment(this, 'DeployWebsite', {
sources: [s3deploy.Source.asset('./website')],
destinationBucket: websiteBucket,
distribution,
distributionPaths: ['/*'],
});
// CloudWatchダッシュボード
const dashboard = new cloudwatch.Dashboard(this, 'WebsiteDashboard', {
dashboardName: 'handson-website-dashboard',
});
dashboard.addWidgets(
new cloudwatch.GraphWidget({
title: 'CloudFront Requests',
left: [
new cloudwatch.Metric({
namespace: 'AWS/CloudFront',
metricName: 'Requests',
dimensionsMap: {
DistributionId: distribution.distributionId,
Region: 'Global',
},
statistic: 'Sum',
period: cdk.Duration.minutes(5),
}),
],
}),
new cloudwatch.GraphWidget({
title: 'CloudFront Error Rate',
left: [
new cloudwatch.Metric({
namespace: 'AWS/CloudFront',
metricName: '4xxErrorRate',
dimensionsMap: {
DistributionId: distribution.distributionId,
Region: 'Global',
},
statistic: 'Average',
period: cdk.Duration.minutes(5),
}),
new cloudwatch.Metric({
namespace: 'AWS/CloudFront',
metricName: '5xxErrorRate',
dimensionsMap: {
DistributionId: distribution.distributionId,
Region: 'Global',
},
statistic: 'Average',
period: cdk.Duration.minutes(5),
}),
],
}),
);
// 出力
new cdk.CfnOutput(this, 'DistributionDomainName', {
value: distribution.distributionDomainName,
description: 'CloudFrontのURL',
});
new cdk.CfnOutput(this, 'BucketName', {
value: websiteBucket.bucketName,
description: 'S3バケット名',
});
}
}
Positive : OAC(Origin Access Control)を使用することで、S3バケットへの直接アクセスをブロックし、CloudFront経由のみでアクセスを許可できます。
初めてCDKを利用する場合は、ブートストラップを実行します。
cdk bootstrap aws://{アカウントID}/ap-northeast-1
Negative : {アカウントID} は自分のAWSアカウントIDに置き換えてください。
デプロイ前に変更内容を確認します。
cdk diff
cdk deploy
デプロイ中に確認が求められた場合は y を入力します。
Positive : デプロイには数分かかる場合があります。CloudFrontディストリビューションの作成に特に時間がかかります。
デプロイが完了すると、以下のような出力が表示されます。
Outputs:
HandsonStaticHostingStack.DistributionDomainName = d1234567890.cloudfront.net
HandsonStaticHostingStack.BucketName = handson-website-{アカウントID}
出力されたCloudFrontのURLにブラウザでアクセスします。
https://d1234567890.cloudfront.net
以下を確認しましょう。
handson-website-dashboard を選択Positive : CloudFrontのメトリクスはリアルタイムではなく、数分の遅延がある場合があります。
Webサイトの内容を更新したい場合は、website/ ディレクトリのファイルを編集し、再デプロイします。
cdk deploy
CDKが自動的にS3のファイルを更新し、CloudFrontのキャッシュを無効化します。
CDKで作成したリソースは、以下のコマンドで一括削除できます。
cdk destroy
確認が求められた場合は y を入力します。
Positive : CDKの RemovalPolicy.DESTROY と autoDeleteObjects: true を設定済みのため、S3バケットも含めて全て自動削除されます。
CDKブートストラップで作成されたS3バケットとCloudFormationスタックが残ります。
完全にクリーンアップしたい場合は以下を実行してください。
cdk-hnb659fds-assets-{アカウントID}-ap-northeast-1 バケットを空にして削除CDKToolkit スタックを削除Negative : CDKブートストラップを削除すると、次回CDKを使用する際に再度ブートストラップが必要になります。他のCDKプロジェクトにも影響するため、削除は慎重に行ってください。
このハンズオンでは以下のことを学びました。
[AWS CDK ドキュメント](https://docs.aws.amazon.com/ja_jp/cdk/)
[Amazon CloudFront ドキュメント](https://docs.aws.amazon.com/ja_jp/cloudfront/)
[Amazon S3 ドキュメント](https://docs.aws.amazon.com/ja_jp/s3/)
[Amazon CloudWatch ドキュメント](https://docs.aws.amazon.com/ja_jp/cloudwatch/)