コンテンツにスキップ

AstroサイトをAWSにデプロイする

AWSは、Astroサイトのデプロイに使用できる、機能豊富なウェブアプリホスティングプラットフォームです。

プロジェクトをAWSにデプロイするには、AWSコンソールを使用する必要があります。(これらのアクションのほとんどは、AWS CLIを使用しても実行できます)。このガイドでは、AWSにサイトをデプロイする手順を最も基本的な方法から説明します。その後、コスト効率とパフォーマンスを向上させるための追加サービスをデモンストレーションします。

AWS Amplifyは、フロントエンドのWebおよびモバイル開発者が、AWS上で迅速かつ容易にフルスタックアプリケーションを構築できるようにするという目的のために設計されたツールと機能のセットです。

  1. 新しいAmplify Hostingプロジェクトを作成します。

  2. リポジトリをAmplifyに接続します。

  3. ビルド出力ディレクトリ baseDirectory/dist に変更します。

    version: 1
    frontend:
    phases:
    preBuild:
    # npmを使用していない場合は、`npm ci` を `yarn install` または `pnpm i` に変更してください。
    commands:
    - npm ci
    build:
    commands:
    - npm run build
    artifacts:
    baseDirectory: /dist
    files:
    - '**/*'
    cache:
    paths:
    - node_modules/**/*

pnpm を使用する場合は、node_modules の代わりに pnpm store ディレクトリをキャッシュするために、設定を変更する必要があります。以下は推奨のビルド設定です.

version: 1
frontend:
phases:
preBuild:
commands:
- npm i -g pnpm
- pnpm config set store-dir .pnpm-store
- pnpm i
build:
commands:
- pnpm run build
artifacts:
baseDirectory: /dist
files:
- '**/*'
cache:
paths:
- .pnpm-store/**/*

Amplifyは、あなたがリポジトリにコミットをプッシュすると、自動的にあなたのウェブサイトをデプロイし、更新します。

S3はあらゆるアプリケーションの出発点です。プロジェクトファイルやその他のアセットが保存されます。S3はファイルの保存容量とリクエスト数に対して課金されます。S3についての詳細はAWS documentationを参照してください。

  1. プロジェクト名を含んだS3バケットを作成します。

  2. **「パブリックアクセスをすべてブロック」**を無効にします。デフォルトでは、AWS はすべてのバケットを非公開に設定しています。公開するには、バケットのプロパティにある「パブリックアクセスをブロック」のチェックを外す必要があります。

  3. distにあるビルドしたファイルをS3にアップロードします。これは、コンソールで手動で行うか、AWS CLIを使用して行うことができます。AWS CLIを使用する場合は、AWS認証情報で認証の後に、以下のコマンドを使用できます。

    aws s3 cp dist/ s3://<BUCKET_NAME>/ --recursive
  4. パブリックアクセスを許可するために、バケットポリシーを更新します。この設定は、バケットのアクセス権限 > バケットポリシーにあります。

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "PublicReadGetObject",
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::<BUCKET_NAME>/*"
    }
    ]
    }
  5. BucketのWebサイトホスティングを有効にします。この設定は、バケットのプロパティ > 静的ウェブサイトホスティングにあります。インデックスドキュメントをindex.htmlに、エラードキュメントを404.htmlに設定します。最後に、バケットのプロパティ > 静的ウェブサイトホスティングで、新しいウェブサイトのURL確認できます。

CloudFrontは、コンテンツ・デリバリー・ネットワーク(CDN)機能を提供するウェブサービスです。ウェブサーバーのコンテンツをキャッシュし、エンドユーザーに配信するために使用されます。CloudFrontは転送されたデータ量に応じて課金されます。CloudFrontをS3バケットに追加することで、より費用対効果が高く、より高速な配信が可能になります。

CloudFrontを使用してS3バケットをラップし、AmazonグローバルCDNネットワークを通じてプロジェクトのファイルを配信します。これにより、プロジェクトのファイルを配信するコストが削減され、サイトのパフォーマンスが向上します。

  1. プロジェクト名を含んだS3バケットを作成します。

  2. dist にあるビルドしたファイルをS3にアップロードします。これは、コンソールで手動で行うか、AWS CLIを使用して行うことができます。AWS CLIを使用する場合は、AWS認証情報で認証した後に、以下のコマンドを使用します。

    aws s3 cp dist/ s3://<BUCKET_NAME>/ --recursive
  3. バケットポリシーを更新し、CloudFrontからのアクセスを許可します。この設定は、バケットのアクセス権限 > バケットポリシーにあります。

    {
    "Version": "2012-10-17",
    "Statement": [{
    "Effect": "Allow",
    "Principal": {
    "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <CLOUDFRONT_OAI_ID>"
    },
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::astro-aws/*"
    }]
    }
  1. 以下の値でCloudFrontディストリビューションを作成します:
    • オリジンドメイン: 作成したS3バケット
    • S3バケットへのアクセス: “OAIを使用する(バケットはCloudFrontのみにアクセスを制限できる)”
    • オリジンアクセスアイデンティティ: 新しいOAIを作成
    • ビューワーバケットポリシー: “いいえ、バケット・ポリシーを更新します。”
    • ビューワープロトコルポリシー: “Redirect to HTTPS”
    • デフォルトルートオブジェクト: index.html

この設定は、パブリックインターネットからのS3バケットへのアクセスをブロックし、グローバルCDNネットワークを使用してサイトを提供します。CloudFrontの配信URLは、バケットのDistributions > Domain nameで確認できます。

残念ながら、CloudFrontはデフォルトでは複数ページのsub-folder/indexルーティングをサポートしていません。これを設定するには、CloudFront Functionsを使ってリクエストをS3の目的のオブジェクトに向ける必要があります。

  1. 以下のコードスニペットで新しいCloudFront関数を作成します。CloudFront関数はCloudFront > 関数にあります。

    function handler(event) {
    var request = event.request;
    var uri = request.uri;
    // URIにファイル名が欠けているかチェックする。
    if (uri.endsWith('/')) {
    request.uri += 'index.html';
    }
    // URIにファイル拡張子が欠けているかチェックする。
    else if (!uri.includes('.')) {
    request.uri += '/index.html';
    }
    return request;
    }
  2. CloudFrontディストリビューションに関数をアタッチします。このオプションは、CloudFrontディストリビューションの設定 > ビヘイビア > 編集 > 関数で見つけることができます。

    • ビューワーリクエスト - 関数タイプ: CloudFrontの関数。
    • ビューワーリクエスト - 関数 ARN: 前のステップで作成した機能を選択します。

S3はデフォルトで、ファイルが見つからなかった場合には404エラーを、ファイルがプライベートであった場合には403エラーを返します。いずれの場合でも、ユーザーは汚いXMLエラーページを見ることとなります。

これを変更するには、CloudFrontディストリビューションの設定 > エラーページカスタムエラーレスポンスを追加します。

  1. 404エラーのためのカスタムエラーレスポンスを以下の値で設定します:

    • HTTPエラーコード: 404: Not Found
    • エラーレスポンスをカスタマイズ: Yes
    • レスポンスページのパス: /index.html
    • HTTPレスポンスコード: 200: OK
  2. 403エラーのためのカスタムエラーレスポンスを以下の値で設定します:

    • HTTPエラーコード: 403: Forbidden
    • エラーレスポンスをカスタマイズ: Yes
    • レスポンスページのパス: /index.html
    • HTTPレスポンスコード: 200: OK

AWSで継続的デプロイを設定する方法はたくさんあります。GitHub 上でホストされているコードの場合、GitHub Actions を使ってコミットをプッシュするたびにウェブサイトをデプロイする方法があります。

  1. AWSアカウントでIAMを使って、以下の権限で新しいポリシーを作成します。このポリシーによって、ビルドしたファイルをS3バケットにアップロードしたり、コミットをプッシュしたときにCloudFrontの配布ファイルを無効にしたりできるようになります。

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "VisualEditor0",
    "Effect": "Allow",
    "Action": [
    "s3:PutObject",
    "s3:ListBucket",
    "s3:DeleteObject",
    "cloudfront:CreateInvalidation"
    ],
    "Resource": [
    "<DISTRIBUTION_ARN>",
    "arn:aws:s3:::<BUCKET_NAME>/*",
    "arn:aws:s3:::<BUCKET_NAME>"
    ]
    }
    ]
    }
  2. 新しいIAMユーザーを作成し、そのユーザーにポリシーをアタッチします。これにより、AWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_IDが提供されます。

  3. 以下のサンプルワークフローをあなたのリポジトリの.github/workflows/deploy.ymlに追加し、GitHubにプッシュしてください。AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYBUCKET_ID、および DISTRIBUTION_IDを、GitHubリポジトリのSettings > Secrets > Actionsから”secrets”として追加する必要があります。New repository secretをクリックして、各値を追加します。

    name: Deploy Website
    on:
    push:
    branches:
    - main
    jobs:
    deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
    uses: actions/checkout@v4
    - name: Configure AWS Credentials
    uses: aws-actions/configure-aws-credentials@v1
    with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: us-east-1
    - name: Install modules
    run: npm ci
    - name: Build application
    run: npm run build
    - name: Deploy to S3
    run: aws s3 sync --delete ./dist/ s3://${{ secrets.BUCKET_ID }}
    - name: Create CloudFront invalidation
    run: aws cloudfront create-invalidation --distribution-id ${{ secrets.DISTRIBUTION_ID }} --paths "/*"

その他のデプロイガイド