
静的サイトを作ったら、それをホスティングする必要があります。個人の趣味サイトなら簡単で無料の方法はGithub Pagesですが、もう少し真面目に静的コンテンツを管理してホスティングしたいのであればAmazon S3は有力な選択肢になります。今回は、S3で静的コンテンツを独自ドメインでSSL化してホスティングする方法を紹介します。
はじめに
今回はReactで作った静的コンテンツをAmazon S3でホスティングする方法を紹介します。それだけでは物足りないので、独自ドメイン対応、SSL化までやっていきます。それでは、始めましょう。
前提
この記事を楽しむには以下が必要です。
- NodeJSがインストール済みであること
- AWS CLIがインストール済みであること
- ドメインを取得済みであること
静的サイトの作成
まずはホスティングする静的サイトを作ります。
準備
Reactでちゃちゃっとサンプルサイトを作ることにしましょう。
$ npm install -g create-react-app
$ create-react-app my-website
$ cd my-website/
静的サイトの作成
今回はReactアプリケーションを作ることが目的ではないので、App.jsの画面に表示される文字を変更するだけにします。
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Hosting a React Welcom Page on S3</h1>
</header>
<p className="App-intro">
Amazon S3 is easy stuff for hosting a static website.
</p>
</div>
);
}
}
export default App;
はい、完成です。
S3バケットの作成と静的サイトのデプロイ
次にS3バケットに作ったサンプルサイトをデプロイしましょう。
S3バケットの作成
S3バケットはAWSコンソールから作ってもよいのですが、AWS CLIから作ってみましょう。
$ aws s3 ls
$ aws s3 mb s3://mywebsite-hosting
make_bucket: mywebsite-hosting
$ aws s3 ls
2018-07-07 11:00:52 mywebsite-hosting
ビルドしてデプロイ
$ yarn build
$ ls
README.md build/ node_modules/ package.json public/ src/ yarn.lock
$ aws s3 sync build s3://mywebsite-hosting
$ aws s3 website s3://mywebsite-hosting --index-document index.html
AWSコンソールでS3バケットを確認してみましょう。
作成したS3バケット上にビルドしたファイルが全てアップロードされています。
作成したS3バケットがホスティングされています。
S3バケットのポリシー設定
S3バケットにアップロードしたファイルはデフォルトではアクセスが許可されていないので、誰でも見れるようにポリシーを変更します。
今回は以下のポリシーを設定しました。S3のポリシーはジェネレーターサイトを使うことでGUIで作成できます。
{
"Version": "2012-10-17",
"Id": "Policy1530901313146",
"Statement": [
{
"Sid": "Stmt1530901311070",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mywebsite-hosting/*"
}
]
}
表示できるか確認します。AWSのS3のコンソールから、エンドポイントを確認します。
エンドポイントをブラウザで開きます。
サンプルサイトがホスティングされていることが確認できました。
独自ドメインの設定
次に、ホスティングしているサンプルサイトに独自ドメインを設定しましょう。
Route53に独自ドメインを登録する
AWSのRoute53のコンソールから、「Hosted zones -> Create Hosted Zone」を選択し、「Domain Name」に取得済みのドメイン名を入力し、「Create」をクリックします。
作成されたHosted zoneのNSレコードのValueをDNSに設定します。
DNSの例として、ムームードメインの場合は、以下のように設定し、「ネームサーバ設定変更」をクリックします。
CloudFrontでエンドポイントとドメインを紐付ける
AWSのCloudFrontのコンソールから、「Create Distribution」をクリックします。
今回は静的サイトを扱うので、Webの「Get Started」をクリックします。
「Origin Domain Name」にS3バケットのエンドポイントのURL(今回の場合は「http://mywebsite-hosting.s3-website-us-east-1.amazonaws.com/」)を入力します。すると、自動的に「Origin ID」が設定されます。
ファイルを圧縮して配信したい場合は「Compress Objects Automatically」を「Yes」にします。
「Price Class」には配信するロケーションを指定します。日本も配信する場合は「Use All Edge Locations」を選択します。「Alternate Domain Names」にはドメイン名を入力します。
「Default Root Object」には「index.html」と入力します。そして、「Create Distribution」をクリックします。
「Status」が「Deployed」になればCloudFrontの設定は完了です。
Route53にCloudFrontを紐付ける
AWSのRoute53のコンソールから、「Create Record Set」をクリックします。今回はサブドメインを利用しないので、Nameは空にします。そして、「Alias」に「Yes」を選択し、「Alias Target」に先程作成したCloudFrontのDistributionの設定を選択します。「Create」をクリックします。
以下のようにAレコードが追加されました。
これで独自ドメインでサンプルサイトが表示できるようになりました。
無料でSSL化
それでは無料でSSLに対応しましょう。
AWS Certificate Manager(ACM)で無料のSSL証明書を発行する
AWSのCertificate Managerのコンソールから、「Request a certificate」をクリックします。
「Domain name」にドメイン名またはサブドメイン名を入力し、「Next」をクリックします。
「DNS validation」を選択し、「Review」をクリックします。
「Confirm and request」をクリックします。
「Continue」をクリックします。
このままだとStatusが「Pending validation」のままなので、「Create record in Route 53」からバリデーション用のレコードを追加します。
「Create」をクリックします。
以下のようにSUCCESSが表示されたら、Route53に設定されていることを確認します。
以下のようにAWSのRoute53のコンソールにバリデーション用のCNAMEレコードが追加されていることが確認できます。
しばらく待つと、AWSのCertificate Managerのコンソールから、以下のように「Status」が「Issued」になり、SSL証明書の発行が完了します。
CloudFrontにSSL証明書を設定する
AWSのCloudFrontのコンソールから、対象のDistributionを選択します。
「General」を選択し、「Edit」をクリックします。
「SSL Certificate -> Custom SSL Certificate」を選択し、先程の発行したSSL証明書を選択します。「Yes, Edit」をクリックします。
以下のように「SSL Certificate」にSSL証明書が設定されていることを確認します。
これでSSL証明書の設定は完了です。
HTTPをHTTPSにリダイレクトするように設定する
SSL化されたのでHTTPSのみにしてもよいのですが、ユーザーがブラウザにHTTPでURLを入力する場合もありえるので、HTTPで入力された場合にHTTPSにリダイレクトするように設定します。
「Behaviors」を選択し、デフォルトのBehaviorを選択して「Edit」をクリックします。
「Viewer Protocol Policy」に「Redirect HTTP to HTTPS」を選択して、「Yes, Edit」をクリックします。
以下のように「Viewer Protocol Policy」が「Redirect HTTP to HTTPS」に変更されていることを確認します。
しばらくして「Status」が「Deployed」になれば、上記の設定変更の反映は完了です。
動作確認
最後にブラウザに独自ドメインのURLを入力してみましょう。
SSLで正しく表示されました。
おまけ
CloudFrontのキャッシュ削除の方法
S3バケットを更新した後にコンテンツをすぐに反映させるにはCloudFrontのキャッシュを削除する必要があります。AWS CLIを使って以下のようにキャッシュを削除できます。
$ yarn build
$ aws s3 sync build s3://mywebsite-hosting
$ curl -I https://yourdomain.com/
...
x-cache: Hit from cloudfront
...
$ aws cloudfront list-distributions --output text --query 'DistributionList.Items[*].[Id]'
EKZEZML5DJ0UB
$ aws cloudfront get-distribution --output json --id EKZEZML5DJ0UB
$ aws cloudfront create-invalidation --distribution-id EKZEZML5DJ0UB --paths '/index.html'
$ aws cloudfront get-invalidation --distribution-id EKZEZML5DJ0UB --id IP17L4GZGHHAK --output text --query 'Invalidation.Status'
Completed
$ curl -I https://yourdomain.com/
...
x-cache: Miss from cloudfront
...
もちろんAWSのCloudFrontのコンソールからも同様の操作ができます。その場合は、「Create Invalidation」をクリックします。
そして、削除したい「Object Paths」を入力して、「Invalidate」をクリックします。
これでキャッシュクリアも完了です。
コンテンツを配信するドメインを指定する方法
画像や動画などのリンクは他のWebサイトに貼られても表示されてしまいます。それを防ぎたい場合は以下のようにS3バケットのポリシーにコンディションを指定することで、表示するドメインを限定できます。
{
"Version": "2012-10-17",
"Id": "Policy1530901313146",
"Statement": [
{
"Sid": "Stmt1530901311070",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mywebsite-hosting/*",
"Condition": {
"StringLike": {
"aws:Referer": "http://yourdomain.com/*"
}
}
}
]
}
S3とCloudFrontのCORSの対応方法
CORS(Cross-Origin Resource Sharing)はオリジンサーバ以外からデータを取得する仕組みですが、S3とCloudFrontの両方を利用している場合は両方共対応する必要があります。
S3のCORS対応
対象のS3バケットを選び、「Permissions -> CORS configuration」から、以下のようにXMLを設定し、「Save」すればOKです。
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
CloudFrontのCORS対応
対象のDistributionを選んで、「Behaviors」タブからデフォルトのBehaviorを選んで「Edit」します。
「Cache Based on Selected」から「Whitelist」を選択します。
「Whitelist Headers」に「Origin」を選択して「Add >>」します。
後は保存して、変更が反映されれば完了です。
AWSコンソールを英語表記にする方法
この記事ではAWSコンソールは英語表記になっています。デフォルトでは日本語表記になっていると思うので、AWSコンソールのフッターから、「English (US)」を選択すれば英語表記にできます。
英語表記にするメリットは、日本語表記にした場合にAWSのUI変更についていくのが大変なのでそれを回避できる点と、何か問題があった時にググることを簡単にする点です。なので、よほど英語アレルギーがある人以外は英語表記にすることをおすすめします。
最後に
いかがでしたか?これでS3上に静的コンテンツを独自ドメインで公開できるようになったと思います。サーバーサイドを作らないのであれば、この方法で十分ですね。それでは。
環境
- NodeJS: v10.5.0
- create-react-app: 1.5.2
- AWS CLI: aws-cli/1.15.40 Python/3.6.5 Darwin/17.6.0 botocore/1.10.40