はじめに
「インフラは AWS でいいけど、デプロイは GitHub Actions でやりたい」——クラウドと Git を組み合わせたハイブリッドな CI/CD 構成は、多くの現場で採用されています。このハンズオンでは、EC2(Tomcat)への自動デプロイを GitHub Actions + AWS CodeDeploy で実現します。
さらに実務でよく見かける「社内共通ライブラリを GitHub Packages で管理・共有する」仕組みも体験できます。Spring Boot WAR をビルドする際に共通ライブラリを GitHub Packages からフェッチし、CodeDeploy で EC2 にデプロイするまでの一連のフローです。
[GitHub リポジトリ]
├── common-lib/ → push → GitHub Actions → GitHub Packages に publish
└── app/ → push → GitHub Actions
├── GitHub Packages から common-utils を取得
├── mvn package → webapp.war
├── zip → S3 にアップロード
└── CodeDeploy を呼び出す
↓
[EC2: Tomcat + Spring Boot WAR] my-ec2app
↓
[ALB: my-ec2app-alb] ← インターネット
↓
[RDS MySQL: my-ec2app-rds]このハンズオンで体験できること:
- GitHub Packages を使った共通ライブラリの管理・共有
- GitHub Actions(OIDC 認証)で AWS にキーレスアクセス
- CodeDeploy + appspec.yml を使った EC2 へのデプロイ自動化
- SSM Parameter Store でデータベースパスワードを安全に管理
- CloudFormation によるインフラ一括構築(VPC / EC2 / ALB / RDS / CodeDeploy)
コード詳細は GitHub を参照してください。
-->
キーワード解説
| 用語 | 意味 |
|---|---|
| GitHub Packages | GitHub リポジトリ内で Maven/npm などのパッケージを管理・共有するレジストリ。社内共通ライブラリの配布に使える |
| GitHub Actions OIDC | アクセスキーをリポジトリに保存せず、JWT トークンで AWS を操作するキーレス認証方式 |
| CodeDeploy | EC2 への WAR 配置・サービス停止/起動・ヘルスチェックを自動化する AWS のデプロイサービス |
| appspec.yml | CodeDeploy がデプロイ時に実行するファイル配置先とフックスクリプト(BeforeInstall / AfterInstall / ValidateService)を定義するファイル |
| SSM Parameter Store | DB パスワードなどの設定値を暗号化して管理し、EC2 から安全に取得できる AWS のサービス |
| CloudFormation | AWS リソースをコード(YAML/JSON)で定義・一括管理する IaC サービス |
| ALB(Application Load Balancer) | HTTP/HTTPS をリスンして EC2 にリクエストを振り分けるロードバランサー |
① 全体構成を理解する
このハンズオンの主役は 2 つのワークフローです。
①-1 common-lib のパブリッシュ(ec2-publish-lib.yml)
common-lib/ が変更されると起動し、Maven ライブラリを GitHub Packages に publish します。actions/setup-java が settings.xml を自動生成するため、認証設定は不要です。
①-2 アプリのデプロイ(ec2-app-deploy.yml)
app/ が変更されると起動します。処理の流れは次の通りです:
① OIDC で AWS に認証
② GitHub Packages から common-utils を取得しながら mvn package で WAR をビルド
③ zip 化して S3 にアップロード(webapp.war + appspec.yml + scripts/)
④ CodeDeploy でローリングデプロイ(〜1〜2 分)デプロイパッケージの構造:
deploy.zip
├── webapp.war ← Tomcat の webapps/ に配置
├── appspec.yml ← CodeDeploy の設定
└── scripts/
├── stop_server.sh ← Tomcat を停止・古い WAR を削除
├── start_server.sh ← SSM から DB 情報を取得・Tomcat 起動
└── validate_service.sh ← /api/health を最大 60 秒リトライ確認② OIDC 認証と IAM ロールを設定する
GitHub Actions が AWS に安全にアクセスするための OIDC(OpenID Connect)認証 を設定します。アクセスキーをリポジトリに保存せずに AWS を操作できる現代的な方式です。
②-1 OIDC プロバイダーを登録する(初回のみ)
AWS コンソール → IAM → 「IDプロバイダー」→「プロバイダーを追加」
| 項目 | 値 |
|---|---|
| プロバイダータイプ | OpenID Connect |
| プロバイダー URL | https://token.actions.githubusercontent.com |
| 対象者(Audience) | sts.amazonaws.com |
ECS ハンズオン(cdk-ecs-webapp)完了済みの場合はスキップ可。
②-2 IAM ロールを作成する
AWS CloudShell で以下を実行します(GITHUB_OWNER と REPO は自分のリポジトリに合わせて変更):
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
GITHUB_OWNER="your-github-username" # ← 自分の GitHub ユーザー名
REPO="your-github-repo" # ← 自分の GitHub リポジトリ名
EMPLOYEE_ID="my" # ← 好きなプレフィックス(例: 123456)
ROLE_NAME="${EMPLOYEE_ID}-github-actions-role"
cat > /tmp/trust-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:${GITHUB_OWNER}/${REPO}:ref:refs/heads/main"
}
}
}]
}
EOF
aws iam create-role \
--role-name $ROLE_NAME \
--assume-role-policy-document file:///tmp/trust-policy.json
# 権限ポリシーを付与(S3 + CodeDeploy)
cat > /tmp/permissions.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::${EMPLOYEE_ID}-ec2app-deploy-*/*"
},
{
"Effect": "Allow",
"Action": [
"codedeploy:CreateDeployment",
"codedeploy:GetDeployment",
"codedeploy:GetDeploymentConfig",
"codedeploy:RegisterApplicationRevision"
],
"Resource": "*"
}
]
}
EOF
aws iam put-role-policy \
--role-name $ROLE_NAME \
--policy-name "${ROLE_NAME}-policy" \
--policy-document file:///tmp/permissions.json
# ロール ARN を表示
aws iam get-role --role-name $ROLE_NAME --query Role.Arn --output text出力された ロール ARN(arn:aws:iam::...)をコピーしておきます。
③ GitHub Variables を設定する
GitHub リポジトリ → Settings → Secrets and variables → Actions → 「Variables」タブ
「New repository variable」で以下を追加します:
| Name | 例 | 説明 |
|---|---|---|
EMPLOYEE_ID | my | リソース名プレフィックス |
AWS_ROLE_ARN | arn:aws:iam::... | ②-2 で表示されたロール ARN |
AWS_ACCOUNT_ID | 123456789012 | AWS アカウント ID(S3 バケット名に使用) |
Variables vs Secrets:ARN や ID は機密情報ではないため Variables に保存します(パスワード類は Secrets を使う)。
④ CloudFormation スタックを作成する
自分の IP アドレスを確認し(curl https://checkip.amazonaws.com)、CloudFormation でインフラを一括作成します:
aws cloudformation deploy ^
--template-file ec2-github-actions/infra/template.yaml ^
--stack-name my-ec2app ^
--parameter-overrides EmployeeId=my DBPassword=Handson1234! MyIP=123.456.78.901/32 ^
--capabilities CAPABILITY_NAMED_IAM ^
--region ap-northeast-1所要時間:約 10〜15 分(RDS の作成に時間がかかります)
CloudFormation スタックが作成するリソース:
| リソース | 名前 |
|---|---|
| VPC / サブネット / IGW | my-ec2app-vpc |
| EC2(Amazon Linux 2023 + Tomcat 10.1) | my-ec2app |
| ALB | my-ec2app-alb |
| RDS MySQL 8.0 | my-ec2app-rds |
| S3(デプロイアーティファクト保管) | my-ec2app-deploy-{アカウントID} |
| CodeDeploy Application + Deployment Group | my-ec2app |
| SSM Parameter Store(DB 接続情報) | /my/ec2app/db-host, /my/ec2app/db-password |
⑤ スタックの Outputs を確認する
aws cloudformation describe-stacks ^
--stack-name my-ec2app ^
--region ap-northeast-1 ^
--query "Stacks[0].Outputs" ^
--output table| キー | 内容 |
|---|---|
ALBEndpoint | アプリ URL(後で使用) |
DeploymentBucketName | S3 バケット名 |
CodeDeployApplicationName | CodeDeploy アプリ名 |
EC2InstanceId | EC2 インスタンス ID(SSM 接続に使用) |
⑥ common-lib を GitHub Packages に publish する
common-lib/pom.xml と app/pom.xml にある GitHub ユーザー名・リポジトリ名のプレースホルダーを自分のものに変更してから push します:
<!-- common-lib/pom.xml と app/pom.xml の両方を変更 -->
<url>https://maven.pkg.github.com/your-github-username/your-github-repo</url>変更を push すると Publish common-utils to GitHub Packages ワークフローが自動起動します:
cd C:\my-aws\aws-learning-projects
git add ec2-github-actions/common-lib/ ec2-github-actions/app/pom.xml
git commit -m "feat: configure GitHub Packages URL for ec2-github-actions"
git pushGitHub リポジトリ → Actions タブ → Publish common-utils to GitHub Packages の実行を確認します。完了後、Packages タブに common-utils 1.0.0 が表示されます。
ResponseWrapperクラスとは:このハンズオンの共通ライブラリは API レスポンスを{"status":"ok","data":{...}}の統一形式にラップするユーティリティです。チーム開発でレスポンス形式を統一する際によく使われるパターンです。
⑦ アプリを初回デプロイする
app/ の変更を push して Deploy App to EC2 ワークフローを起動します:
cd C:\my-aws\aws-learning-projects
git add ec2-github-actions/app/
git commit -m "feat: initial deploy via GitHub Actions (EC2)"
git push
nothing to commitと表示された場合:index.htmlに空白行を追加して変更を作ります:echo. >> ec2-github-actions\app\src\main\resources\templates\index.html git add ec2-github-actions/app/src/main/resources/templates/index.html git commit -m "chore: trigger initial deploy" git push
⑧ GitHub Actions の進行を確認する
GitHub → Actions タブ → Deploy App to EC2 で各ステップの実行状況を確認します:
| ステップ | 内容 | 時間目安 |
|---|---|---|
| Checkout | コード取得 | 〜10秒 |
| Configure AWS credentials | OIDC 認証(アクセスキー不要) | 〜10秒 |
| Set up Java | JDK 17 + settings.xml 生成 | 〜30秒 |
| Build WAR | GitHub Packages から common-utils 取得 + mvn package | 〜1〜2分 |
| Package and upload to S3 | zip 化 → S3 へアップロード | 〜10秒 |
| Deploy via CodeDeploy | EC2 にデプロイ + 完了待ち | 〜1〜2分 |
合計:約 3〜5 分
ポイントは 「Set up Java」ステップです。actions/setup-java に server-id: github を指定するだけで、GitHub Packages の認証情報を含む settings.xml が自動生成されます。Maven のパスワード設定を手書きする必要はありません。
⑨ ブラウザで動作確認する
ALBEndpoint の URL にアクセスすると「Spring Boot + RDS Item Manager (EC2)」が表示されます。
/api/health にアクセスして以下が返ることも確認します:
{"status":"ok","message":null,"data":"OK"}このレスポンス形式こそが common-utils の ResponseWrapper が GitHub Packages 経由で取得・ビルドされた証拠です。
⑩ CI/CD サイクルを体験する
index.html のタイトルを変更して push すると、約 3〜5 分でブラウザに反映されます:
<!-- 変更後 -->
<h1>Spring Boot + RDS Item Manager (EC2 v2) <span class="badge">GitHub Actions</span></h1>git add ec2-github-actions/app/src/main/resources/templates/index.html
git commit -m "feat: update title to EC2 v2"
git pushこれが CI/CD の醍醐味です。コードを push するだけで自動的にデプロイが完了します。
⑪ SSM Session Manager で EC2 に接続する(オプション)
キーペアなしで EC2 内部を確認できます:
aws ssm start-session ^
--target i-xxxxxxxxxxxxxxxxx ^
--region ap-northeast-1# Tomcat のステータス確認
sudo systemctl status tomcat
# デプロイログの確認
sudo cat /var/log/aws/codedeploy-agent/codedeploy-agent.log
# SSM から取得した DB 接続情報の確認
sudo cat /opt/tomcat/current/bin/setenv.sh
# Tomcat ログの確認
sudo journalctl -u tomcat -n 50setenv.sh を確認すると、SSM Parameter Store から取得した DB ホスト名とパスワードが環境変数としてセットされていることがわかります。パスワードをコードに書かずに安全に注入できています。
⑫ リソースを削除する
① S3 バケットを空にする(デプロイアーティファクトが蓄積されているため先に削除)
aws s3 rm s3://my-ec2app-deploy-123456789012 --recursive② CloudFormation スタックを削除する
aws cloudformation delete-stack ^
--stack-name my-ec2app ^
--region ap-northeast-1
aws cloudformation wait stack-delete-complete ^
--stack-name my-ec2app ^
--region ap-northeast-1
echo スタック削除完了まとめ:学んだ概念
| 概念 | ポイント |
|---|---|
| GitHub Packages | Maven ライブラリを GitHub リポジトリ内で管理・共有する仕組み。社内共通ライブラリの配布に活用できる |
| GitHub Actions OIDC | アクセスキー不要で AWS に認証するキーレス方式。aws-actions/configure-aws-credentials で簡単に設定可 |
| CodeDeploy | EC2 への WAR 配置・サービス再起動・ヘルスチェックを自動化するサービス |
| appspec.yml | CodeDeploy がデプロイ時に実行するファイル配置とフックスクリプトを定義するファイル |
| SSM Parameter Store | DB パスワードをインスタンスに安全に渡す仕組み。start_server.sh から取得して setenv.sh に書き込む |
| CloudFormation | VPC・EC2・RDS・ALB・CodeDeploy を 1 つの YAML テンプレートで一括構築 |
GitHub Actions と AWS を組み合わせることで、Git push だけでインフラから独立してアプリをデプロイできる柔軟な CI/CD パイプラインを構築できます。次のステップとして、EC2 + CodePipeline ハンズオンで完全 AWS ネイティブな CI/CD も体験してみましょう。
コメント