CloudFormationでSpring Boot WebアプリをALB + EC2(Tomcat) + RDS に自動デプロイする手順【S3 + UserData / WAR自動配布】

AWS Basic
スポンサーリンク
スポンサーリンク

はじめに

前回のAWSコンソール版ハンズオン(Spring Boot Webアプリ)では、コンソールでインフラを手動構築してSCPでWARをデプロイしました。

この記事では、同じ構成を CloudFormation で自動化します。template.yaml 1ファイルにVPC・SG・IAM・SSM・RDS・ALB・EC2(約30リソース)を定義し、さらに EC2のUserDataがS3からWARを自動取得してTomcatにデプロイするため、コマンド数本でWebアプリが動く状態まで一気に構築できます。

ローカル環境(VSCode)
  ├── app/target/webapp.war(mvn packageでビルド済み)
  ├── template.yaml(約30リソースを定義)
  └── AWS CLI コマンド
        ↓ スタック作成(コマンド1本)
AWS環境
  ├── S3バケット(webapp.war置き場)
  └── VPC(10.0.0.0/16)
        ├── パブリックサブネット1・2(ALB + EC2)
        ├── プライベートサブネット1・2(RDS)
        ├── IGW + ルートテーブル
        ├── IAMロール(SSM + S3読み取り権限)
        ├── ALB SG → EC2 SG → RDS SG(SG-to-SG制御)
        ├── SSM Parameter Store(/my/webapp/db-password)
        ├── RDS MySQL 8.0(db.t3.micro / sampledb)
        ├── ALB(HTTP:80)→ TG(HTTP:8080)
        └── EC2(t2.micro)
              UserDataが自動実行:
              1. Java + Tomcat インストール
              2. SSMからDBパスワード取得 → setenv.sh作成
              3. S3からwebapp.warをダウンロード → ROOT.warとして配置
              4. Tomcat起動(Spring Bootアプリが自動展開)

このハンズオンで体験できること:

  • WARのデプロイをS3 + UserDataで完全自動化する設計
  • SSMからDB接続情報を取得してsetenv.shを自動作成する仕組み
  • delete-stack 1本でALB・RDS・IAMなど全リソースを自動削除

テンプレートとアプリのソースコードはGitHubで公開しています:

aws-handson/alb-ec2-rds-webapp at main · caymezon/aws-handson
AWS HANDSON. Contribute to caymezon/aws-handson development by creating an account on GitHub.

この記事は AWSコンソール版ハンズオン の比較記事です。
コンソール版でSCPデプロイの仕組みを理解した後に読むと理解が深まります。


-->

スポンサーリンク

CloudFormation vs コンソール:どれだけ違うか

比較項目CloudFormationコンソール(手動)
VPC + サブネット4つ + IGW + ルートテーブルtemplate.yaml に定義済み約20〜30分・複数画面
SG 3つ(ALB/EC2/RDS)の作成template.yaml に定義済み3画面で個別設定
ALB + TG + Listener の作成template.yaml に定義済み3つの画面で設定
WARのデプロイS3 + UserDataで自動SCPで転送 + SSH操作
DB接続設定(setenv.sh)UserDataがSSMから自動取得・作成SSH接続して手動作成
全体のデプロイコマンド数本(RDS待ち15〜20分)約60〜90分
削除delete-stack 1本16ステップ手動

スポンサーリンク

キーワード解説

用語意味
CloudFormationAWSが提供するIaC(Infrastructure as Code)サービス
スタックCloudFormationが管理するリソースのまとまり。今回は約30リソースを1スタックで管理
S3 VPC Gateway EndpointEC2からS3にインターネットを経由せずアクセスするための無料エンドポイント
UserDataEC2初回起動時に自動実行されるシェルスクリプト
CAPABILITY_NAMED_IAM名前付きIAMリソースを含むスタック作成に必要なフラグ
DeletionPolicy: Deleteスタック削除時にRDSも確実に削除する設定

前提条件

aws sts get-caller-identity
aws --version
java -version
mvn -version

構築されるリソース(約30個)

template.yaml の詳細はGitHubを参照してください:

aws-handson/alb-ec2-rds-webapp/template.yaml at main ?? caymezon/aws-handson
AWS HANDSON. Contribute to caymezon/aws-handson development by creating an account on GitHub.
カテゴリリソース
ネットワークVPC / IGW / パブリックサブネット×2 / プライベートサブネット×2 / ルートテーブル×2 / S3 VPC Endpoint
セキュリティALB SG / EC2 SG / RDS SG
IAMEC2ロール(SSM + S3読み取り権限)+ インスタンスプロファイル
パラメータSSM Parameter Store(/my/webapp/db-password
データベースRDS DBサブネットグループ / RDS MySQL 8.0
ロードバランサーターゲットグループ / ALB本体 / リスナー
コンピュートEC2インスタンス(Tomcat + WAR自動デプロイ)

作業順序

⓪ Webアプリをビルドする(mvn package)
      ↓
⓪-2 自分のIPアドレスを確認する
      ↓
① キーペアを作成する(コンソールで実施)
      ↓
② S3バケットを作成してWARをアップロードする
      ↓
③ スタックを作成する(aws cloudformation create-stack)
      ↓
④ 作成完了・Outputsを確認する(RDS待ち15〜20分)
      ↓
⑤ 動作確認(ALBアクセス・アイテム追加削除)
      ↓
⑥ スタックを削除する(S3バケットも忘れず削除)

⓪ Webアプリのビルド

アプリのソースコードはGitHubで公開しています:

aws-handson/alb-ec2-rds-webapp/app at main ?? caymezon/aws-handson
AWS HANDSON. Contribute to caymezon/aws-handson development by creating an account on GitHub.
cd C:\(プロジェクトフォルダ)\alb-ec2-rds-webapp\app
mvn package -DskipTests
dir target\webapp.war

webapp.war(約20〜30MB)が生成されていれば成功です。


⓪-2 自分のIPアドレスを確認する

curl https://checkip.amazonaws.com

控えておく情報: 自分のIPアドレス(例: 203.0.113.1


① キーペアの作成(コンソールで実施)

CloudFormationではキーペアのダウンロードができないため、コンソールで先に作成します。

AWSコンソール → EC2 → キーペア → 「キーペアを作成」

設定項目
名前my-webapp-key
キーペアのタイプRSA
プライベートキーファイル形式.pem

ダウンロードされた my-webapp-key.pem を保存します。

C:\Users\ユーザー名\.ssh\my-webapp-key.pem

② S3バケットの作成とWARのアップロード

EC2のUserDataがS3から webapp.war をダウンロードするため、スタック作成より前にアップロードしておく必要があります。

プロジェクトフォルダに移動する

cd C:\(プロジェクトフォルダ)\alb-ec2-rds-webapp

S3バケットを作成する

バケット名はグローバルで一意である必要があります。末尾に任意の識別子を加えてユニークにしてください。

aws s3 mb s3://my-webapp-bucket-(任意の識別子) --region ap-northeast-1

WARをS3にアップロードする

aws s3 cp app\target\webapp.war s3://my-webapp-bucket-(任意の識別子)/webapp.war

アップロードを確認します。

aws s3 ls s3://my-webapp-bucket-(任意の識別子)/
2026-04-18 10:00:00   26214400 webapp.war

③ スタックの作成

以下のコマンドを実行します。各パラメータを自分の値に置き換えます。

aws cloudformation create-stack ^
  --stack-name my-webapp-stack ^
  --template-body file://template.yaml ^
  --region ap-northeast-1 ^
  --capabilities CAPABILITY_NAMED_IAM ^
  --parameters ^
    ParameterKey=KeyName,ParameterValue=my-webapp-key ^
    ParameterKey=MyIP,ParameterValue=(⓪-2で確認したIP)/32 ^
    ParameterKey=DBPassword,ParameterValue=(任意のパスワード) ^
    ParameterKey=WARBucketName,ParameterValue=my-webapp-bucket-(任意の識別子)

CAPABILITY_NAMED_IAM について: 名前を指定したIAMリソース(EC2ロールなど)を作成する場合に必要なフラグです。

TomcatVersion パラメータについて: デフォルト値は 10.1.28。変更する場合は ParameterKey=TomcatVersion,ParameterValue=10.1.xx を追加します。利用可能なバージョンは https://archive.apache.org/dist/tomcat/tomcat-10/ で確認します。

成功すると以下のような StackId が表示されます。

{
    "StackId": "arn:aws:cloudformation:ap-northeast-1:123456789012:stack/my-webapp-stack/xxxxx"
}

④ 作成完了・Outputsの確認

注意: RDSの作成には約15〜20分かかります。EC2のUserDataでWARのデプロイも行うため、さらに数分かかります。

作成状況の確認

aws cloudformation describe-stacks ^
  --stack-name my-webapp-stack ^
  --query "Stacks[0].StackStatus" ^
  --output text
ステータス意味
CREATE_IN_PROGRESS作成中(待つ)
CREATE_COMPLETE作成完了
ROLLBACK_COMPLETE失敗してロールバック完了(トラブルシューティングを参照)

Outputs(接続情報)の確認

CREATE_COMPLETE になったら以下を実行します。

aws cloudformation describe-stacks ^
  --stack-name my-webapp-stack ^
  --query "Stacks[0].Outputs" ^
  --output table
+--------------------+-------------------------------------------------------------------+
|  OutputKey         |  OutputValue                                                      |
+--------------------+-------------------------------------------------------------------+
|  ALBEndpoint       |  http://my-webapp-alb-1234567890.ap-northeast-1.elb.amazonaws.com |
|  EC2PublicIP       |  x.x.x.x                                                         |
|  RDSEndpoint       |  my-webapp-rds-mysql.xxxxx.ap-northeast-1.rds.amazonaws.com      |
|  DBPasswordParamName |  /my/webapp/db-password                                         |
|  SSHCommand        |  ssh -i ~/.ssh/my-webapp-key.pem ec2-user@x.x.x.x               |
+--------------------+-------------------------------------------------------------------+

控えておく情報: ALBEndpointEC2PublicIPRDSEndpoint


⑤ 動作確認

ALBのヘルスチェック確認

EC2 → ターゲットグループ → my-webapp-tg → 「ターゲット」タブ

EC2のステータスが 「healthy」 になるまで待ちます(EC2起動後5〜10分)。

Tomcatの起動 + WARのデプロイはEC2「実行中」からさらに数分かかります。initialunhealthy が続く場合はしばらく待ちます。

ALB経由でWebアプリにアクセスする

Outputsに表示された ALBEndpoint をブラウザで開きます。

http://(ALBEndpointのDNS名)
Spring Boot + RDS Item Manager
ALB → EC2(Tomcat) → RDS MySQL の3層構成で動作しています。

が表示されれば成功です。

アイテムの追加・削除を試す

  1. テキストボックスにアイテム名を入力して「追加」をクリック
  2. アイテムが一覧に表示されることを確認
  3. 「削除」ボタンでアイテムが削除されることを確認

ブラウザをリロードしてもデータが保持されていれば、RDSへの永続化が成功しています。

(任意)ログでデプロイ過程を確認する

OutputsのSSHCommandでEC2に接続して確認します。

sudo cat /var/log/user-data.log

# Tomcatのログ(Spring Bootのスタートアップログ)
sudo tail -50 /opt/tomcat/logs/catalina.out

# setenv.shの内容確認(DB接続情報が正しく設定されているか)
sudo cat /opt/tomcat/bin/setenv.sh

exit

⑥ スタックの削除

課金を止めるために、ハンズオン完了後は必ず削除します。

スタックを削除する

aws cloudformation delete-stack ^
  --stack-name my-webapp-stack ^
  --region ap-northeast-1

注意: RDS削除には約10〜15分かかります。

削除状況の確認

aws cloudformation describe-stacks ^
  --stack-name my-webapp-stack ^
  --query "Stacks[0].StackStatus" ^
  --output text

削除完了の確認(以下のエラーが表示されれば削除完了):

An error occurred (ValidationError) when calling the DescribeStacks operation:
Stack with id my-webapp-stack does not exist

S3バケットを削除する

S3バケットはCloudFormationで管理していないため手動で削除します。

aws s3 rm s3://my-webapp-bucket-(任意の識別子) --recursive
aws s3 rb s3://my-webapp-bucket-(任意の識別子)

キーペアを削除する(任意)

EC2 → キーペア → my-webapp-key を選択 → 「アクション」→「削除」


コンソール版との比較

作業コンソール版CloudFormation版
VPC + サブネット + IGW + RT約20〜30分template.yaml に定義済み
SG 3つの作成3画面で個別設定template.yaml に定義済み
ALB + TG + Listener3つの画面で設定template.yaml に定義済み
WARのデプロイSCP + SSH操作S3 + UserDataで自動
DB接続設定(setenv.sh)SSH接続して手動作成UserDataがSSMから自動取得・作成
全体のデプロイ約60〜90分コマンド数本(RDS待ち15〜20分)
削除16ステップ手動delete-stack 1本(+S3手動削除)

トラブルシューティング

症状原因対処
CREATE_FAILED → ROLLBACKになるパラメータ不正・リソース上限などコンソールのCloudFormationイベントタブでエラー詳細を確認
ALBに繋がらないWARデプロイがまだ完了していないTGのヘルスチェックがHealthyになるまで待つ(5〜10分)
ヘルスチェックがUnhealthyWAR取得失敗 or Spring Boot起動失敗SSH接続して sudo cat /var/log/user-data.log を確認
NoSuchKey エラーS3にwebapp.warがないaws s3 ls s3://バケット名/ で存在確認
DB接続エラー(500エラー)setenv.shのDB_HOSTが空sudo cat /opt/tomcat/bin/setenv.sh で確認
Tomcatバージョンエラー指定バージョンがアーカイブに存在しないhttps://archive.apache.org/dist/tomcat/tomcat-10/ で確認して TomcatVersion パラメータを更新
DELETE_FAILEDリソースの依存関係が残っているコンソールからALBを手動削除してから delete-stack を再実行

失敗時の詳細確認コマンド

aws cloudformation describe-stack-events ^
  --stack-name my-webapp-stack ^
  --query "StackEvents[?ResourceStatus=='CREATE_FAILED'].[ResourceType,ResourceStatusReason]" ^
  --output table

まとめ

ステップ内容
Mavenで webapp.war をビルド
キーペアをコンソールで作成
S3バケット作成 + WARをアップロード
create-stack 1本(RDS待ち15〜20分)
CREATE_COMPLETE になったらOutputsでALBエンドポイント・EC2IP・RDSエンドポイントを確認
ヘルスチェックがHealthyになったらブラウザでCRUD動作確認
delete-stack 1本 + S3バケット手動削除

CloudFormation版の最大のポイントはWARデプロイの自動化です。コンソール版ではSCPでWARを転送してSSHでsetenv.shを作成する必要がありましたが、今回はS3にWARをアップロードするだけでUserDataが全て自動で行います。

コンソール操作でSCPデプロイの仕組みを手を動かして確認したい場合は、AWSコンソール版ハンズオンを参照してください。

コメント