Closed5

S3 + CloudFront構成で静的サイトをホスティングする

LeivyLeivy

S3バケットの作成

  1. S3の管理画面からバケットの作成を選択
  2. バケットタイプは「汎用」を選択します
    • 汎用 (Standard): 高可用性と耐久性が必要な場合に最適。デフォルトで選択されます。今回は静的ぺージの配信なのでこちらを選択。
    • ディレクトリ・新規 (One Zone-IA): アクセス頻度が低いデータ向けです。単一のAZ (Availability Zone) での保存となるため、コストが低くなりますが、耐久性は標準タイプより低い。
  3. オブジェクト所有者は「ACL無効」を選択
    • ACL無効 (推奨): この設定を選ぶと、オブジェクトの所有権はバケット所有者に自動的に割り当てらる。推奨設定。
    • ACL有効: ACL (アクセスコントロールリスト) を使用する場合はこのオプションを選択しますが、セキュリティリスクがあるため、必要がない場合は使用を避ける。
  4. パブリックアクセス設定では「パブリックアクセスをすべて ブロック」にチェックをいれておきます(後からポリシーを設定する)
  5. バケットのバージョニングは「有効」
  6. あとはデフォルトのまま「バケットを作成」をクリック
LeivyLeivy

S3 バケットにHTMLファイルと画像の配置

  1. index.htmlファイルと必要なファイルを追加
  2. プロパティタブへ移動し、一番下へスクロール
  3. 静的ウェブサイトホスティングを次のように設定し保存
LeivyLeivy

CloudFrontを作成

  1. CloudFrontの管理画面から「ディストリビューションを作成」をクリック
  2. 「Origin domain」に先ほど作成したバケットを選択
  3. 次の警告が出てもとりあえず気にせず続ける
  4. 「Origin path」には/index.htmlと入力
  5. オリジンアクセスでは「Origin access control settings (recommended)」を選択(S3のサイトにはCloudFrontしかアクセスできるようにするため)
  6. 「Create new OAC」でコントロール設定を新しく作成する
  7. ビューワープロトコルポリシーでは「Redirect HTTP to HTTPS」を選択。これでhttpのアクセスもhttpsにリダイレクトしてくれる
  8. Alternative domain name (CNAMEs) では使用したいドメインを入力
  9. 証明書はCloudFrontで使う場合はバージニア北部リージョンで証明書を発行しなければならないので、ない場合は新しく発行する。同じドメインで別リージョンに証明書を発行することは問題なく、追加料金もかからない(参考)
  10. 他はそのままで下へ進み、「デフォルトルートオブジェクト」にindex.htmlと入力し「ディストリビューションを作成」をクリック
  11. オリジンタブへ移動し、作成されたディストリビューションのオリジンを選択し、「編集」をクリック
  12. 「ポリシーをコピー」を選択し、「S3バケットアクセス許可に移動」を選択しS3のバケットポリシーのリンクに移動
  13. 「アクセス許可」タブの「バケットポリシー」の「編集」をクリックし、コピーしたポリシーを貼り付けて保存
  14. 「ディストリビューションドメイン名」をコピーしてアクセスし、ページが表示されれば完了

ドメインと紐づけ

  1. Route53のホストゾーンから使用したいドメインを選択
  2. 使用したいドメインのAレコードに作成したCloudFrontディストリビューションを選択
  3. 保存し、しばらくしてドメインへアクセス(しばらくかかる)
  4. 表示されれば完了
LeivyLeivy

GitHub Actions でページを更新できるようにする

参考

https://oji-cloud.net/2023/05/06/post-7451/

IAMロールの作成

今回はIAM ユーザー (アクセスキー) を作成する代わりに、IAM のID プロバイダ (IdP)を使用します。この結果、外部ユーザー ID (GitHub Actions) にAWS アカウント内の AWS リソースに対するアクセス許可を与えることができます。

  1. IAMの管理画面から「ID プロバイダ」を選択し、「プロバイダを追加」を選択
  2. プロバイダのタイプ: 「OpenID Connect」
  3. プロバイダのURL : https://token.actions.githubusercontent.com
  4. 対象者: sts.amazonaws.com
  5. 「プロバイダを追加」
  6. 作成されたら画面上部に出現する「ロールの割り当て」をクリック
  7. 「新しいロールを作成」のまま次へ
  8. 「ウェブアイデンティティ」を選択し、それぞれ画像のように指定
  9. GitHub 組織に任意のものを入力して次へ
  10. 許可ポリシーは新しく作成し、以下の内容を入力※[bucket-name]は実際のバケット名に置き換える
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:ListBucket",
                    "s3:DeleteObject"
                ],
                "Resource": [
                    "arn:aws:s3:::[bucket-name]",
                    "arn:aws:s3:::[bucket-name]/*"
                ]
            }
        ]
    }
    
  11. 作成したポリシーを割り当ててロールを作成

GitHub Actionsのワークフロー作成

今回は以下のように作成しました

name: 【デプロイ】ページをS3へデプロイ

on:
  workflow_dispatch:
  push:
    branches:
      - master
  pull_request:
    types:
      - closed
    branches:
      - development

env:
  AWS_REGION: <your-region>
  AWS_ROLENAME: <your-role-name>
  AWS_S3_BUCKET: <your-bucket-name>
  SOURCE_DIR: '.'
  ENV_NAME: html-page

jobs:
  Deploy:
    name: S3デプロイ
    runs-on: ubuntu-22.04
    if: (github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged && !startsWith(github.event.pull_request.head.ref, 'renovate/')) || (github.event_name != 'pull_request')
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: AWSへの認証情報を設定
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::${{secrets.AWS_ACCOUNT_ID}}:role/${{env.AWS_ROLENAME}}
          aws-region: ${{ env.AWS_REGION }}

      - name: デプロイを開始をSlackへ通知する
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          text: "デプロイを開始します -> ${{ env.ENV_NAME }}"
          fields: repo,message,commit,author,action,eventName,ref,workflow
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

      - name: ファイルの整合性チェック
        run: |
          if [ ! -f "${{ env.SOURCE_DIR }}/index.html" ]; then
            echo "Error: index.html not found in ${{ env.SOURCE_DIR }}"
            exit 1
          fi

      - name: Copy files to S3
        run: |
          aws s3 sync ${{env.SOURCE_DIR}} s3://${{env.AWS_S3_BUCKET}} --exclude '.*git*' --delete
        continue-on-error: false

      - name: S3デプロイの確認
        run: |
          aws s3 ls s3://${{env.AWS_S3_BUCKET}} --summarize --human-readable

      - name: 結果をSlackに通知
        uses: 8398a7/action-slack@v3
        if: always()
        with:
          status: ${{ job.status }}
          text: "デプロイ ${{ job.status == 'success' && '成功' || '失敗' }} -> ${{ env.ENV_NAME }}"
          fields: repo,message,commit,author,action,eventName,ref,workflow
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

最後に

作成したGitHub Actionsが問題なく実行され、S3上のファイルが更新されれば完了です

このスクラップは2024/09/02にクローズされました