背景
CDK PipelinesにCodeDeployを組み合わせて、Spring Boot WARのホットデプロイまで自動化するハンズオンをやりました。インフラのCI/CDだけだった前段のハンズオンから、アプリのCI/CDまで踏み込んだ内容です。
1. appspec.ymlが3つのライフサイクルフックを順番に実行する
version: 0.0
os: linux
files:
- source: webapp.war
destination: /opt/tomcat/webapps/
overwrite: true
hooks:
ApplicationStop:
- location: scripts/stop_tomcat.sh # Tomcat停止
BeforeInstall:
- location: scripts/cleanup.sh # 古いWAR・展開ディレクトリを削除
AfterInstall:
- location: scripts/start_tomcat.sh # Tomcat起動
CodeDeployはappspec.ymlに定義された順序でフックスクリプトを実行し、Tomcatを完全に再起動することなくWARファイルを差し替えます。「停止→クリーンアップ→配置→起動」という定型的なホットデプロイの手順がYAML1枚に集約されています。
2. env_from_cfn_outputsでスタック出力をパイプラインの環境変数として受け取る
# webapp_stack.py側: CfnOutputでリソース名を公開
self.deploy_app_name_output = CfnOutput(
self, "DeployApplicationName",
value=web.deploy_application.application_name,
)
# pipeline_stack.py側: 環境変数として受け取る
build_and_deploy = CodeBuildStep(
"BuildAndDeployApp",
env_from_cfn_outputs={
"DEPLOY_APP_NAME": stage.deploy_app_name_output,
},
commands=["aws deploy create-deployment --application-name $DEPLOY_APP_NAME ..."],
)
CodeDeployのアプリケーション名をパイプラインのコードにハードコードせず、CloudFormationが実際に作成したリソース名を動的に環境変数として受け取ります。これにより、リソース名の変更がCloudFormation側で起きても、パイプラインのコードを修正する必要がありません。
3. postステップで「インフラ確定後にアプリをデプロイする」順序を保証する
pipeline.add_stage(stage, post=[build_and_deploy])
postにステップを渡すことで、ステージ(InfraDeploy)の完了後に続けてBuildAndDeployAppが実行される順序が保証されます。EC2やCodeDeployのリソースがまだ存在しない状態でデプロイを試みる、という順序ミスを防げます。
4. パイプラインは全ファイル(Javaソース含む)のpushを前提にする
cdk deploy の前に必ずプロジェクト全体を push する必要がある
理由: パイプラインがGitHubから取得したコードで cdk synth と mvn package を両方実行するため
インフラのみをCI/CD化していた前段のハンズオンとは異なり、app/配下のJavaソース・appspec.yml・scripts/がリポジトリに存在しないと、パイプラインのBuildAndDeployAppステップ自体が失敗します。ローカルの作業ディレクトリだけに置いたファイルはパイプラインからは見えません。
5. URLパスに/webapp/が必要な理由もWARのデプロイ形式に起因する
http://<ALBEndpoint>/ ← Tomcatのデフォルト画面
http://<ALBEndpoint>/webapp/ ← デプロイしたSpring Bootアプリ
webapp.warという名前でデプロイされるため、アプリは/webapp/というコンテキストパス以下に配置されます。ルートパスのままではTomcatの初期画面が表示され続けるため、アプリ本体を見るには明示的にパスを付ける必要があります。
まとめ
appspec.ymlによるホットデプロイの定型化と、env_from_cfn_outputsによるリソース名の動的受け渡しが、このハンズオンでのCodeDeploy連携のポイントでした。インフラとアプリの両方がgit pushだけで反映される状態を実現することで、AWSコンソールでの手動変更が入り込む余地をなくす設計です。