メインコンテンツに移動

builders.flash

AWS CLI で完結する Amplify Hosting の CI/CD デプロイとロールバック

2026-08-03 | Author : 岡本 秀高 (CircleCI 合同会社)

Missing alt text value

はじめに

AWS Amplify Hosting は、静的サイトからモダンなSSR(サーバーサイドレンダリング)Webアプリまでを迅速にデプロイ・管理できるフルマネージドサービスです。

開発者はインフラ(CDNやサーバー設定など)を意識することなく、ソースコードやビルド成果物をアップロードするだけで世界中にセキュアに配信できます。また、デプロイした内容に問題が見つかったときは、過去のバージョンの成果物を再デプロイすることで、ワンクリックでロールバックが可能です。

一方で、ソースコードから再ビルドして戻す方法では、アプリケーションの規模が大きくなるほどビルドに時間がかかり、障害発生時の平均復旧時間(MTTR)が長くなりやすくなります。継続的デリバリーの考え方では、一度ビルドした成果物をそのまま再利用し、同じ内容を作り直さないことが望ましいとされています。この考え方は継続的デリバリーで「Build once, deploy many」と呼ばれ、ビルドのたびに依存関係の解決結果が変わり得るリスクを避け、検証済みの成果物だけを本番に届ける目的で用いられます。

Amplify Hosting では、 Amazon Simple Storage Service (Amazon S3) に保管したビルド済みの成果物を直接デプロイできます。この方法を使えば、再ビルドを挟むことなく、任意のバージョンへの切り替えやロールバックを素早く実行可能です。

本記事では、この S3 を利用したデプロイ を AWS CLI のみで操作し、バージョン別のプレフィックスを用いてデプロイとロールバックを同一の仕組みで実現する手順を解説します。

 

X ポスト » | Facebook シェア » | はてブ »

builders.flash メールメンバー登録

builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。

今すぐ登録 »

登場するサービスと全体構成

本記事で扱う AWS サービスは次の 2 つです。

  • AWS Amplify Hosting : 静的サイトのホスティングと配信を担います
  • Amazon Simple Storage Service (Amazon S3) : デプロイする成果物を保管します

今回はロールバック可能な形でコンテンツをアップロード・デプロイする方法をシンプルに再現するため、リリースごとに S3 のプレフィックスを用意する方法を選びました。初回のリリースは releases/v1/ 、2 回目は releases/v2/ のような形で配置し、プレフィックス内のファイルを指定して Amplify Hosting へのデプロイ指示を行います。この方法を採用することで、過去のバージョンにロールバックしたい場合も、該当バージョンのプレフィックスをデプロイコマンドで指定するだけで OK です。実際のアプリケーション運用では、tar などで圧縮したビルドファイルを S3 バケットに配置し、ファイル名またはプレフィックスに git tag のバージョンや git の commit SHA を付与しましょう。

Missing alt text value

S3 バケットと Amplify アプリのセットアップ

最初に、作業全体で使う環境変数を設定します。今回は東京リージョン (ap-northeast-1) にて作業を行います。他のリージョンを利用する場合は、AWS Amplify が利用可能なリージョンであることを事前に確認してください。

bash
# リージョンとアカウント ID を設定
export AWS_REGION=ap-northeast-1
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)

# バケット名・アプリ名・ブランチ名・リリース用プレフィックスを設定
export BUCKET_NAME="amplify-s3-deploy-${ACCOUNT_ID}-$(date +%s)"
export APP_NAME="amplify-s3-rollback-demo"
export BRANCH_NAME="main"
export RELEASE_PREFIX="releases"

S3 バケットを作成

次に、成果物を保管する S3 バケットを作成します。us-east-1 以外のリージョンでは --create-bucket-configuration LocationConstraint の指定が必要です。指定しない場合は IllegalLocationConstraintException が発生します。バケットを作成する際の挙動については CreateBucketConfiguration をご確認ください。

bash
# バケットを作成(ap-northeast-1 では LocationConstraint が必須)
aws s3api create-bucket \
  --bucket "$BUCKET_NAME" \
  --region "$AWS_REGION" \
  --create-bucket-configuration LocationConstraint="$AWS_REGION"

Amplify アプリとブランチを作成

続いて、Amplify アプリと、デプロイ先となるブランチを作成しましょう。今回は AWS Amplify Hosintg の自動ビルドを使用しません。そのため --no-enable-auto-build をコマンドに追加します。

bash
# Amplify アプリを作成し、アプリ ID を取得
export APP_ID=$(aws amplify create-app \
  --name "$APP_NAME" \
  --platform WEB \
  --query 'app.appId' \
  --output text)

# デプロイ先ブランチを作成
aws amplify create-branch \
  --app-id "$APP_ID" \
  --branch-name "$BRANCH_NAME" \
  --stage PRODUCTION \
  --no-enable-auto-build

バケットポリシーを設定

次はAmplify Hosting が S3 バケットの成果物を読み取れるよう、バケットポリシーを設定しましょう。ここでは、対象を自分のアカウントと作成したブランチに限定し、暗号化されていない通信を拒否しています。 aws:SourceArn に渡すブランチ ARN は、URL エンコードした文字列を指定する必要がありますので注意しましょう。

バケットポリシー
bash
# ブランチ ARN を URL エンコード
BRANCH_ARN="arn:aws:amplify:${AWS_REGION}:${ACCOUNT_ID}:apps/${APP_ID}/branches/${BRANCH_NAME}"
ENCODED_BRANCH_ARN=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${BRANCH_ARN}', safe=''))")

# バケットポリシーを作成
mkdir -p policies
cat > policies/bucket-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAmplifyToListBucket",
      "Effect": "Allow",
      "Principal": { "Service": "amplify.amazonaws.com" },
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::${BUCKET_NAME}",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "${ACCOUNT_ID}",
          "aws:SourceArn": "${ENCODED_BRANCH_ARN}"
        }
      }
    },
    {
      "Sid": "AllowAmplifyToGetObject",
      "Effect": "Allow",
      "Principal": { "Service": "amplify.amazonaws.com" },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::${BUCKET_NAME}/*",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "${ACCOUNT_ID}",
          "aws:SourceArn": "${ENCODED_BRANCH_ARN}"
        }
      }
    },
    {
      "Sid": "DenyInsecureTransport",
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::${BUCKET_NAME}",
        "arn:aws:s3:::${BUCKET_NAME}/*"
      ],
      "Condition": { "Bool": { "aws:SecureTransport": "false" } }
    }
  ]
}
EOF

# バケットポリシーを適用
aws s3api put-bucket-policy \
  --bucket "$BUCKET_NAME" \
  --policy file://policies/bucket-policy.json

これで S3 バケットを経由した AWS Amplify Hosting へのデプロイ準備が整いました。次からは簡単な HTML ファイルを利用してデプロイとロールバックを実践してみましょう。

AWS Amplify Hosting へ AWS CLI からデプロイする

まず、最初のバージョン(v1)をデプロイしてみます。まずはデプロイする HTML ファイルを作成します。ファイルパスは、わかりやすさを重視して artifacts/v1/index.html としましょう。

bash
<!DOCTYPE html><html><body><h1>Amplify S3 Deploy - v1</h1></body></html>

ファイルをアップロード

ファイルが作成できましたので、releases/v1/ プレフィックスでアップロードしましょう。

bash
# v1 のファイルが生成できていることを確認
ls -la artifacts/v1/index.html

# バージョン別プレフィックスへアップロード
export VERSION="v1"
export S3_PREFIX="${RELEASE_PREFIX}/${VERSION}/"
aws s3 sync "artifacts/${VERSION}/" "s3://${BUCKET_NAME}/${S3_PREFIX}"

成果物をデプロイ

アップロードした成果物を、start-deployment コマンドで Amplify Hosting にデプロイします。--source-url-type BUCKET_PREFIX を指定することで、S3 バケットとプレフィックスをソースとして扱えます。

bash
# v1 をデプロイ
aws amplify start-deployment \
  --app-id "$APP_ID" \
  --branch-name "$BRANCH_NAME" \
  --source-url "s3://${BUCKET_NAME}/${S3_PREFIX}" \
  --source-url-type BUCKET_PREFIX

サイト URL を取得

デプロイしたAWS Amplify Hostingのサイトにアクセスしてみましょう。URLはamplify get-appコマンドで取得できます。

bash
aws amplify get-app --app-id "$APP_ID" --query 'app.defaultDomain' --output text
dbp09tcrezris.amplifyapp.com

URL にアクセス

URL にアクセスすると、「Amplify S3 Deploy \- v1」が表示されます。

Missing alt text value

現在のバージョンを保存

続いて、ロールバック時にどのバージョンへ戻すかを判断できるよう、現在のバージョンを S3 上の状態ファイルに記録しておきます。

bash
# 現在のバージョンを記録
mkdir -p state
echo "${VERSION}" > state/current-release.txt
aws s3 cp state/current-release.txt "s3://${BUCKET_NAME}/state/current-release.txt"

新しいバージョンをデプロイ

同じ流れで、新しいバージョンをデプロイしましょう。まず新しいバージョンの HTML を保存します。今回のファイルパスは artifacts/v2/index.html とします。

bash
<!DOCTYPE html><html><body><h1>Amplify S3 Deploy - v2</h1></body></html>

新しいファイルをアップロード

その後、再び AWS CLI を利用して Amazon S3 へアップロードし、 AWS Amplify へのデプロイまで実行します。デプロイ前に、現在のバージョンを PREVIOUS_VERSION として控えておきましょう。

bash
# v2 ファイルが作成済みであることを確認
ls -la artifacts/v2/index.html

# 直前のバージョンを控える
export PREVIOUS_VERSION=$(cat state/current-release.txt)

# v2 をアップロードしてデプロイ
export VERSION="v2"
export S3_PREFIX="${RELEASE_PREFIX}/${VERSION}/"
aws s3 sync "artifacts/${VERSION}/" "s3://${BUCKET_NAME}/${S3_PREFIX}"
aws amplify start-deployment \
  --app-id "$APP_ID" \
  --branch-name "$BRANCH_NAME" \
  --source-url "s3://${BUCKET_NAME}/${S3_PREFIX}" \
  --source-url-type BUCKET_PREFIX

# 記録を v2 に更新
echo "${VERSION}" > state/current-release.txt
aws s3 cp state/current-release.txt "s3://${BUCKET_NAME}/state/current-release.txt"

表示内容を確認

デプロイ後は、配信 URL にアクセスして表示内容を確認できます。

bash
# 配信 URL の内容を確認
curl -sS -H "Cache-Control: no-cache" https://${BRANCH_NAME}.${APP_ID}.amplifyapp.com/

ブラウザからアクセス

ブラウザからアクセスすると、 Amplify S3 Deploy - v2 が表示され、v2 が反映されていることがわかります。

Missing alt text value

AWS CLI からロールバックする

それでは、V2 に問題が発生したと想定して前のバージョンにロールバックしてみましょう。ロールバックは、控えておいた前バージョンのプレフィックスを、デプロイと同じ start-deployment コマンドに渡すだけで実現できます。

bash
# 前バージョン(v1)のプレフィックスを指定して再デプロイ
export ROLLBACK_VERSION="${PREVIOUS_VERSION}"
export S3_PREFIX="${RELEASE_PREFIX}/${ROLLBACK_VERSION}/"
aws amplify start-deployment \
  --app-id "$APP_ID" \
  --branch-name "$BRANCH_NAME" \
  --source-url "s3://${BUCKET_NAME}/${S3_PREFIX}" \
  --source-url-type BUCKET_PREFIX

# 記録を v1 に戻す
echo "${ROLLBACK_VERSION}" > state/current-release.txt
aws s3 cp state/current-release.txt "s3://${BUCKET_NAME}/state/current-release.txt"

ブラウザでアクセス

ロールバック後にブラウザでアクセスすると、 Amplify S3 Deploy - v1 が表示されています。

Missing alt text value

コマンドで確認する場合

コマンドで確認する場合は、以下のようにキャッシュヘッダーをつけておくと良いでしょう。

bash
curl -sS -H "Cache-Control: no-cache" https://main.xxxx.amplifyapp.com/

記録成功 !

Amplify コンソールのデプロイ履歴にも、デプロイとロールバックの 3 件がいずれも成功として記録されました。

このようにして、AWS CLIを利用して任意のバージョンをAWS Amplify Hostingへ手早くデプロイ・ロールバックできます。

Missing alt text value

CI/CD パイプラインへの組み込み例

ここまでの手順は、CI/CD パイプラインのデプロイジョブにそのまま組み込めます。ここでは CircleCI を実行環境とした例を示します。CircleCI には、デプロイを記録する deploy markers と、記録したバージョンへ Web アプリから切り戻す rollback pipeline の機能があります。circleci run release plan でデプロイを計画として記録し、ジョブの成否に応じて circleci run release update で結果を更新する流れになります。

通常のデプロイは、Git タグの push を起点に動かす構成にします。タグ名 (CIRCLE_TAG) をリリースバージョンとして、deploy marker と S3 プレフィックスの両方に反映します。AWS への認証には CircleCI の OIDC を使い、AWS_ROLE_ARN AWS_REGION をコンテキスト (ここでは aws-oidc) に登録しておきます。

実際のデプロイコマンド

bash
# .circleci/config.yml(デプロイ用)
version: 2.1

orbs:
  aws-cli: circleci/aws-cli@5.4.0

jobs:
  deploy:
    docker:
      - image: cimg/base:current
    steps:
      - checkout
      - aws-cli/setup:
          role_arn: $AWS_ROLE_ARN
          region: $AWS_REGION
      - run:
          name: Plan deployment
          command: |
            circleci run release plan amplify-hosting \
              --environment-name=production --component-name=web \
              --target-version=$CIRCLE_TAG
      - run:
          name: Sync to S3 and deploy to Amplify Hosting
          command: |
            aws s3 sync "artifacts/${CIRCLE_TAG}/" \
              "s3://${BUCKET_NAME}/releases/${CIRCLE_TAG}/"
            aws amplify start-deployment \
              --app-id "${APP_ID}" --branch-name "${BRANCH_NAME}" \
              --source-url "s3://${BUCKET_NAME}/releases/${CIRCLE_TAG}/" \
              --source-url-type BUCKET_PREFIX
      - run:
          name: Update release status to SUCCESS
          command: circleci run release update amplify-hosting --status=SUCCESS
          when: on_success
      - run:
          name: Update release status to FAILED
          command: circleci run release update amplify-hosting --status=FAILED
          when: on_fail

workflows:
  deploy:
    jobs:
      - deploy:
          context: aws-oidc
          filters:
            tags: { only: /^v.*/ }
            branches: { ignore: /.*/ }

ロールバックも同じような作りで、別途 .circleci/rollback.yml を用意します。CIRCLE_TAG<< pipeline.deploy.target_version >> に置き換え、release plan--rollback フラグを付ければ動きます。rollback pipeline を使うには、事前に GitHub App の導入と、Project Settings の Deploys から rollback pipeline の登録が必要です。
deploy markers と rollback pipeline の設定手順の詳細は、Rollback a deployment を参照してください。

リソース削除

検証後に料金が発生しないよう、作成したリソースを削除します。

bash
# Amplify アプリを削除
aws amplify delete-app --app-id "$APP_ID"

# S3 バケットの中身を削除してからバケットを削除
aws s3 rm "s3://${BUCKET_NAME}" --recursive
aws s3 rb "s3://${BUCKET_NAME}"

まとめ

本記事では、AWS CLI だけを使って、Amplify Hosting への S3 デプロイとロールバックを実現する手順を解説しました。バージョン別のプレフィックスへビルド済みの成果物を分けて保管し、start-deployment --source-url-type BUCKET_PREFIX でデプロイすることで、ロールバックを同じコマンドで扱えるようになります。過去の成果物をそのまま再利用するため、切り戻し時に再ビルドが不要で、障害発生時の復旧を短時間で進められます。CLIで全ての操作が行えますので、独自に構築・運用されている CI/CD パイプラインに組み込みやすいでしょう。

この仕組みは、リリースの世代管理や、特定バージョンへの切り戻しを伴う運用にも応用できます。読者の皆様が Amplify Hosting の運用手順を整える際の一助となれば幸いです。

各 AWS サービスの料金は、AWS Amplify の料金Amazon S3 の料金をご参照ください。 

筆者プロフィール

岡本 秀高
CircleCI 合同会社 
Senior Field Engineer

AWS や Cloudflare 上へのサーバーレスなアプリ開発を得意とする開発者。
元 Stripe Developer Advocate / AWS Samurai 2017 など、サービスの使い方や活用 Tips を紹介するコンテンツ作成や登壇などを得意とする。
和太鼓・打楽器プレイヤーのヒカセン。

Missing alt text value