sagara.inkITエンジニアのまとめノート

AWS S3+CloudFrontに静的Webサイトを設置し、GitHub+CircleCIでデプロイ環境を構築する

静的サイトをホスティングする場合、AWSのS3とCloudFrontを利用することができます。 さらに、GitHubからCircleCiで変更があったら自動できるにデプロイされる方法を紹介します。 また、Route53での独自ドメインと、ACMで発行した証明書の設定も行います。

AWS S3+CloudFrontで静的Webサイトを設置

まずは静的Webサイトをホスティングするために、 AWSのストレージサービスであるS3とコンテンツ配信サービスであるCloudFrontを使います。

S3バケットの作成

S3は、Googleドライブのようなクラウドストレージのように、バケットの中に画像や文書ファイルなどを保存しておくことができます。

S3の保存領域にはバケットという単位があります。 バケットは、レンタルサーバーを借りると割り当てられる1つのユーザー領域に相当すると考えてよいと思います。

S3の「バケットの作成」から、バケットの情報を入力します。

fig1

バケット名はそのAWSリージョン内でただ一つの名前にする必要があります。
なお、あとでCloudFrontで設定をするので、ここではバケットポリシーの変更や公開設定は必要ありません。

CloudFrontのディストリビューションを作成

S3バケットをそのまま外部公開(静的サイトホスティング)することも可能ですが、 TLS接続(HTTPS接続)に対応していません。 HTTPSでS3に接続するためには、SSL/TLS証明書を設定するためにCloudFrontが必要です。

CloudFrontは、コンテンツ配信用のサービスで、ユーザーとS3などAWSリソースとのあいだに立ち、 リクエストごとの処理を挟んだり、コンテンツをキャッシュしてレスポンスを高速化することができます。

CloudFrontのサービスの単位をディストリビューションと呼びます。 先ほど作成したS3バケットを参照するディストリビューションを作成しましょう。

fig2

オリジンドメインに先ほど作成したS3バケットが表示されるので選択します。 自動的にディストリビューションの名前が入力されます。

fig3

S3をCloudFront経由で公開するために、「S3バケットアクセス」の設定を変更します。
「はい、OAI を使用します (バケットは CloudFront のみへのアクセスとなるように制限できます)」 を選択するとさらに「オリジンアクセスアイデンティティ」「バケットポリシー」の項目が表示されます。
オリジンアクセスアイデンティティでは「新しいOAIを作成」し、 バケットポリシーで「はい、バケットポリシーを自動で更新します」を選択します。
(S3のバケットポリシーが自動的に変更されます。)

あとの項目は現時点では設定する必要はありません。 最下部の「ディストリビューションの作成」でディストリビューションを作成します。

fig4

先ほど作成したS3のバケットポリシーを見ると、自動的に設定されているのがわかります。

S3バケットに適当なファイル(例えばsample.html)を置き、 ディストリビューションの設定タブの「ディストリビューションドメイン名」 (**************.cloudfront.net/sample.html)にブラウザでアクセスすると、 S3バケットの内容にアクセスすることができます。

IAMユーザーとアクセスキーの作成

(補足)ルートユーザ、IAMユーザ、IAMロールとは

AWSアカウントを発行したときに作成するのがルートユーザです。 しかし、普段の開発や運用で使用するのは適切な権限を持つアカウントを利用するのが望ましいです。 AWSではIAMという機能があり、 AWSの各サービスに対する権限を管理します。

IAMには種類があり、個人に対して与えるIAMユーザと、 サービスなどの役割に対して与えるIAMロールが存在します。

AWSのコンソールには、ルートユーザでもIAMユーザでもログインできます。 例えば誰かとアカウントを共有する場合、それぞれにIAMユーザを割り当てて管理するのが良いでしょう。 IAMユーザによって許可する権限を変更したり、必要がなくなったらアクセス権限を削除するなどの対応が可能です。

アクセスキーを発行

IAMユーザーがない場合、CircleCIからS3にアクセスするためのIAMユーザを作成します。
なお、S3へのアクセス権限のあるユーザーである必要があります。

  • (IAMユーザーがない場合)IAM→「ユーザーを追加」からIAMユーザを作成
  • ユーザー名→認証情報→アクセスキーから「アクセスキーの作成」
  • アクセスキーとシークレットアクセスキーをメモする。

シークレットアクセスキーを確認できるのは1度きりなので注意してください。
ここで発行したアクセスキーとシークレットアクセスキーはCircleCIの設定に使用します。

GitHub+CircleCIでデプロイ環境を構築する

では、GitHubを更新したら自動的にS3に反映されるようにCIの設定をしていきます。

CIとは継続的インテグレーション(Continuous Integration)のことで、ソースコードの変更などを契機とし、自動的にテストやビルドなどのタスクを行う手法のことです。
継続的デリバリー(Continuous Delivery)とあわせて、CI/CDと呼ばれたりします。テスト・ビルド・デプロイ(リリース)の一連の流れを自動化することができます。
CircleCIはCIを実現するためのツールであり、SaaSなのでCI用のサーバーを別途立てたりする必要ありません。GitHubと連携できるので、GitHubアカウントがあれば簡単に始められます。

CircleCIの設定

あらかじめGitHubのレポジトリに公開したいHTMLを配置しておきます。

CircleCIはGitHubのアカウントでログインすることができます。ダッシュボードにログインすると、GitHub上のレポジトリが一覧になっているのがわかります。 CIの稼働状況やタスクの実行結果などは、ここに表示されます。

Circle CI

.circleci/config.ymlを作成

レポジトリのルートに.circleci(先頭にドットあり)というディレクトリを作成し、 その配下にcircleci.ymlというファイルを配置します。
ここにCircleCIが実行するタスクなどの設定を記入していきます。

.circleci/config.yml
version: 2.1
jobs:
  build:
    docker:
      - image: cimg/python:3.6
    steps:
      - checkout
      - run: mkdir bucket && cd bucket/ && git clone {{GitHubレポジトリのURL}} .
      - aws-s3/sync:
        arguments: |
          —acl public-read           —cache-control “max-age=86400”
        aws-access-key-id: AWS_ACCESS_KEY_ID
        aws-region: AWS_REGION
        aws-secret-access-key: AWS_SECRET_ACCESS_KEY
        from: bucket
        to: 's3://{{S3バケット名}}/'
orbs:
  aws-s3: circleci/aws-s3@2.0.0

GitHubレポジトリのURL、およびS3のバケット名はそれぞれ変更してください。 また、AWS_ACCESS_KEY_ID、AWS_REGION、AWS_SECRET_ACCESS_KEYは定数ですが、これについては後述します。

CircleCIはconfig.ymlのsteps:配下に記載の順にタスク実行していきます。ここでは、3つのタスクがあります。

  • checkout: CircleCIの実行に必要な機能を準備する。
  • run: ここではbucketディレクトリを作成し、その中にGitHubのレポジトリをクローンする。
  • aws-s3/sync: 作成したbucketディレクトリと、AWSのS3バケットの中身を同期する。
yaml
      - run: mkdir bucket && cd bucket/ && git clone {{GitHubレポジトリのURL}} .

CircleCI上のbucketディレクトリに、GitHubのレポジトリをクローンします。

yaml
        from: bucket
          to: 's3://{{S3バケット名}}/'

そして、bucketディレクトリの内容をS3バケットと同期しています。

環境変数を設定

前項のconfig.ymlにはAWSのアクセスキーを設定する必要があります。
これらをconfig.yml上に直接書いてしまうと、秘密にすべき情報が公開されてしまう恐れがあるので、CircleCIの環境変数として設定しておきます。

  1. Project Settings→Environment Variablesの順に選択
  2. 「Add Environment Variable」を押し、NameにAWS_ACCESS_KEY_ID、Valueにアクセスキーを入力し保存する
  3. 同様に、AWS_SECRET_ACCESS_KEY、AWS_REGIONも登録する

先ほどIAMユーザーに紐づけて生成したアクセスキーとシークレットアクセスキーを入力します。
AWS_REGIONは、東京リージョンの場合はap-northeast-1になります。
これで、CircleCI上でこれらの環境変数を利用することができます。

デプロイできるかどうかを確認する

GitHubレポジトリのメインブランチに変更をプッシュしてみましょう。CircleCIの管理画面を見ると、レポジトリの変更を検知してCIが動いているのがわかります。

fig5

独自ドメインとHTTPS接続に対応する

DNSの設定

ドメインの準備

AWSが提供するDNSサービスはRoute53です。 ドメインはRoute53のコンソール上で取得することもできますし、他社で取得したものを利用することもできます。 筆者の場合は、料金が手ごろなお名前.comで購入したものを利用しています。

取得したドメインをWebサイトと紐付けるためには、DNS(Domain Name System)の設定をする必要があります。 一般的には、DNSサーバーはドメイン取得サービスが同時に提供していますが、必ずしもそのDNSサーバーを利用する必要はありません。
ここでは、Route53でDNS設定を行います。

お名前.comなどのドメイン取得サービスを利用する場合

今回はRoute53のDNSを使用しますので、ドメイン取得サービスの管理画面上でそのドメインの利用DNS設定を行います。 Route53の4つネームサーバー(ホストゾーン→ドメイン名→NSレコードで確認できます)を、お名前.comなどの管理画面上で設定します。 以下はお名前.comの場合の設定方法です。

  1. 「ネームサーバー設定」→「ネームサーバーの変更」
  2. ドメインを選択し、「その他のサービス」「その他のネームサーバを使う」を選択
  3. Route53の4つのネームサーバーを登録する

Route53のDNS設定

まず、ホストゾーンを作成します。1つのドメインに紐づく設定をホストゾーンに記載します。

  1. 「ホストゾーン」→「ホストゾーンの作成」を選択
  2. 「ドメイン名」に取得したドメイン名を入力、「タイプ」は「パブリックホストゾーン」を選択
  3. 「ホストゾーンの作成を押す

次に、ドメインとCloudFront(に紐づくS3バケット)を繋げるためのDNSレコードを作成します。

  1. 「ホストゾーン」→「レコードを作成」を選択
  2. レコード名は空白、レコードタイプは「A - IPv4アドレスと一部のAWSリソース…」を入力
  3. 「値」の横の「エイリアス」スイッチをオンにし、「トラフィックのルーティング先」を表示する
  4. 「エンドポイントを選択」で「CloudFrontディストリビューションへのエイリアス」を選択
  5. 「ディストリビューションを選択」に、作成したディストリビューションドメイン名を入力
  6. 「レコードの作成」を押す

ディストリビューションドメイン名は、「**************.cloudfront.net」のことです。

fig6

少しわかりづらいですが、「値」の横の「エイリアス」スイッチをオンにすると 「トラフィックのルーティング先」の設定が出現します。

fig7

「CloudFrontディストリビューションへのエイリアス」を選択すると、続けて「ディストリビューションの選択」が表示されます。 作成したCloudFrontディストリビューションのドメイン名を入力します。

しばらく待ってからアクセスすると、作成したドメインでS3バケットの内容が表示されるようになります。

SSL/TLS証明書の設定

証明書の発行は面倒になりがちですが、AWSのCertificate Manager(ACM)で簡単に発行できます。

Certificate ManagerでSSL/TLS証明書を発行する

まずはドメイン用のSSL/TLS証明書を発行します。 注意点として、CloudFrontでSSL証明書を使うためには、バージニア北部リージョンで証明書を取得する必要があります。

fig8

「完全修飾ドメイン名」に証明書を発行する対象のドメインを記入します。
検証方法は「DNS検証」を選択し、 「リクエスト」を送信します。

fig11

ステータスが「保留中の検証」になり、詳細を確認するとドメインの所有者であることの証明が必要になります。 DNS検証を選択した場合は、ここに表示されるCNAMEレコードをRoute53の対象ドメインのレコードに追加すればOKです。

Validating domain ownership
  1. Route53の「ホストゾーン」→「レコードを作成」を選択
  2. レコード名にDNS検証で表示されたCNAME名を入力
  3. レコードタイプは「CNAME - 別のドメイン名および一部のAWSリソースに…」を選択
  4. 値にDNS検証で表示されたCNAME値を入力
  5. 「レコードの作成」を押す
fig9

認証局の審査が通ると証明書が発行され、CloudFrontで利用することができるようになります。 DNS検証の場合、CNAMEを設定してから72時間以内に認証されるようです。楽しみに待ちましょう。

証明書をCloudFrontに設定する

ディストリビューション設定の編集

CloudFront→設定→「編集」を選択し、「カスタムSSL証明書」に先ほど発行された証明書を設定します。

fig10
ビヘイビアの設定

「ビューワープロトコル」で、「Redirect HTTP to HTTPS」を設定します。 httpsでアクセスした場合にhttpsにリダイレクトさせます。