AWS CLI で完結する Amplify Hosting の CI/CD デプロイとロールバック
2026-08-03 | Author : 岡本 秀高 (CircleCI 合同会社)
はじめに
AWS Amplify Hosting は、静的サイトからモダンなSSR(サーバーサイドレンダリング)Webアプリまでを迅速にデプロイ・管理できるフルマネージドサービスです。
開発者はインフラ(CDNやサーバー設定など)を意識することなく、ソースコードやビルド成果物をアップロードするだけで世界中にセキュアに配信できます。また、デプロイした内容に問題が見つかったときは、過去のバージョンの成果物を再デプロイすることで、ワンクリックでロールバックが可能です。
一方で、ソースコードから再ビルドして戻す方法では、アプリケーションの規模が大きくなるほどビルドに時間がかかり、障害発生時の平均復旧時間(MTTR)が長くなりやすくなります。継続的デリバリーの考え方では、一度ビルドした成果物をそのまま再利用し、同じ内容を作り直さないことが望ましいとされています。この考え方は継続的デリバリーで「Build once, deploy many」と呼ばれ、ビルドのたびに依存関係の解決結果が変わり得るリスクを避け、検証済みの成果物だけを本番に届ける目的で用いられます。
Amplify Hosting では、 Amazon Simple Storage Service (Amazon S3) に保管したビルド済みの成果物を直接デプロイできます。この方法を使えば、再ビルドを挟むことなく、任意のバージョンへの切り替えやロールバックを素早く実行可能です。
本記事では、この S3 を利用したデプロイ を AWS CLI のみで操作し、バージョン別のプレフィックスを用いてデプロイとロールバックを同一の仕組みで実現する手順を解説します。
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 を付与しましょう。
S3 バケットと Amplify アプリのセットアップ
最初に、作業全体で使う環境変数を設定します。今回は東京リージョン (ap-northeast-1) にて作業を行います。他のリージョンを利用する場合は、AWS Amplify が利用可能なリージョンであることを事前に確認してください。
# リージョンとアカウント 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 をご確認ください。
# バケットを作成(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 をコマンドに追加します。
# 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 エンコードした文字列を指定する必要がありますので注意しましょう。
バケットポリシー# ブランチ 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 としましょう。
<!DOCTYPE html><html><body><h1>Amplify S3 Deploy - v1</h1></body></html>
ファイルをアップロード
ファイルが作成できましたので、releases/v1/ プレフィックスでアップロードしましょう。
# 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 バケットとプレフィックスをソースとして扱えます。
# 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コマンドで取得できます。
aws amplify get-app --app-id "$APP_ID" --query 'app.defaultDomain' --output text
dbp09tcrezris.amplifyapp.com
URL にアクセス
URL にアクセスすると、「Amplify S3 Deploy \- v1」が表示されます。
現在のバージョンを保存
続いて、ロールバック時にどのバージョンへ戻すかを判断できるよう、現在のバージョンを S3 上の状態ファイルに記録しておきます。
# 現在のバージョンを記録
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 とします。
<!DOCTYPE html><html><body><h1>Amplify S3 Deploy - v2</h1></body></html>
新しいファイルをアップロード
その後、再び AWS CLI を利用して Amazon S3 へアップロードし、 AWS Amplify へのデプロイまで実行します。デプロイ前に、現在のバージョンを PREVIOUS_VERSION として控えておきましょう。
# 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 にアクセスして表示内容を確認できます。
# 配信 URL の内容を確認
curl -sS -H "Cache-Control: no-cache" https://${BRANCH_NAME}.${APP_ID}.amplifyapp.com/
ブラウザからアクセス
ブラウザからアクセスすると、 Amplify S3 Deploy - v2 が表示され、v2 が反映されていることがわかります。
AWS CLI からロールバックする
それでは、V2 に問題が発生したと想定して前のバージョンにロールバックしてみましょう。ロールバックは、控えておいた前バージョンのプレフィックスを、デプロイと同じ start-deployment コマンドに渡すだけで実現できます。
# 前バージョン(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 が表示されています。
コマンドで確認する場合
コマンドで確認する場合は、以下のようにキャッシュヘッダーをつけておくと良いでしょう。
curl -sS -H "Cache-Control: no-cache" https://main.xxxx.amplifyapp.com/
記録成功 !
Amplify コンソールのデプロイ履歴にも、デプロイとロールバックの 3 件がいずれも成功として記録されました。
このようにして、AWS CLIを利用して任意のバージョンをAWS Amplify Hostingへ手早くデプロイ・ロールバックできます。
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) に登録しておきます。
実際のデプロイコマンド
# .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 を参照してください。
リソース削除
検証後に料金が発生しないよう、作成したリソースを削除します。
# 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 を紹介するコンテンツ作成や登壇などを得意とする。
和太鼓・打楽器プレイヤーのヒカセン。