S3 + CloudFrontの構成で静的コンテンツ配信する構成をCDKで作ってみた。
YAMLから開放されて非常に良い・・・CDKはいいぞ!
前提
- aws-cdkの実行環境は構築済み
- 今回は TypeScript で構築してます
- Route53の設定済み
- ACMで証明書を発行済み
準備
不足しているパッケージを追加します。
$ npm i -D @aws-cdk/aws-s3 @aws-cdk/aws-cloudfront @aws-cdk/aws-route53-targets
コード
ディレクトリ構成
今回は以下の構成で動かすことを想定しています。l
./
├ bin/
│ └ cdk.ts
└ lib/
└ sample/
└ index.ts
bin/cdk.ts
sample/index.ts
のpropsに値を渡してあげるだけです。
import * as cdk from '@aws-cdk/core';
import { SampleStack } from '../lib/sample';
const app = new cdk.App();
new SampleStack(app, "sample-stack", {
// 公開したいドメイン名を指定(バケット名にもなる)
domain: "sample.xxxxxxx.com",
// 設定済みのRoute53の情報
route53HostedZoneId: "xxxxxxxxx",
route53HostedZoneName: "xxxxxxxxxxx",
// 作成済みの証明書のARN
acmCertificateArn: "arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
// CloudFrontに設定するTTL
cfTtl: cdk.Duration.minutes(5),
});
Stack
import * as core from "@aws-cdk/core";
import * as s3 from "@aws-cdk/aws-s3";
import * as cf from "@aws-cdk/aws-cloudfront";
import * as route53 from "@aws-cdk/aws-route53";
import * as targets from "@aws-cdk/aws-route53-targets";
export interface SampleStackProps extends core.StackProps {
readonly domain: string;
readonly route53HostedZoneId: string;
readonly route53HostedZoneName: string;
readonly acmCertificateArn: string;
readonly cfTtl: core.Duration;
}
export class SampleStack extends core.Stack {
constructor(scope: core.Construct, id: string, props: SampleStackProps) {
super(scope, id, props);
const bucket = new s3.Bucket(this, "S3Bucket", {
bucketName: props.domain,
accessControl: s3.BucketAccessControl.PRIVATE,
removalPolicy: core.RemovalPolicy.DESTROY,
});
const identity = new cf.OriginAccessIdentity(this, "OriginAccessIdentity", {
comment: `${bucket.bucketName} access identity`,
});
const distribution = new cf.CloudFrontWebDistribution(this, "Distribution", {
enableIpV6: true,
httpVersion: cf.HttpVersion.HTTP2,
viewerProtocolPolicy: cf.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
viewerCertificate: {
aliases: [props.domain],
props: {
acmCertificateArn: props.acmCertificateArn,
sslSupportMethod: cf.SSLMethod.SNI,
minimumProtocolVersion: "TLSv1.2_2019",
},
},
originConfigs: [
{
s3OriginSource: {
s3BucketSource: bucket,
originAccessIdentity: identity,
},
behaviors: [
{
isDefaultBehavior: true,
allowedMethods: cf.CloudFrontAllowedMethods.GET_HEAD,
cachedMethods: cf.CloudFrontAllowedCachedMethods.GET_HEAD,
defaultTtl: props.cfTtl,
maxTtl: props.cfTtl,
minTtl: props.cfTtl,
forwardedValues: {
queryString: false,
},
},
],
},
],
});
new route53.ARecord(this, "Route53ARecordSet", {
zone: route53.HostedZone.fromHostedZoneAttributes(this, "Route53HostedZone", {
hostedZoneId: props.route53HostedZoneId,
zoneName: props.route53HostedZoneName,
}),
recordName: props.domain,
target: route53.RecordTarget.fromAlias(new targets.CloudFrontTarget(distribution)),
});
}
}
うごかす
しばらく待ちます・・・
$ cdk deploy sample-stack
sample-stack: deploying...
sample-stack: creating CloudFormation changeset...
[██████████████████████████████████████████████████████████] (7/7)
✅ sample-stack
Stack ARN:
arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/sample-stack/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
確認
とりあえず試したいだけなので、S3にはコンソールから適当なファイルをアップロード済みです
bin/cdk.ts
でSampleStack
に渡したドメインを開くと、ページが表示されるかと思います!
$ open sample.xxxxxxx.com
破棄
今回作った構成は不要なので消しておきます
バケットの中身は事前に空にしておきます
$ cdk destroy sample-stack
Are you sure you want to delete: sample-stack (y/n)? y
sample-stack: destroying...
✅ sample-stack: destroyed