背景
Spring Boot + Maven + Tomcat + RDS MySQLでCRUDアプリを構築するハンズオンをAWSコンソールで手動実施しました。EC2にはApache/Tomcatをインストールするだけでなく、実際にビルドしたWARファイルをデプロイする工程があり、そこで使うsetenv.shという仕組みが実務でも使える知識でした。
1. Tomcatはsetenv.shで環境変数をJVMに渡せる
sudo tee /opt/tomcat/bin/setenv.sh << EOF
export DB_HOST=my-webapp-rds-mysql.xxxxxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com
export DB_PASSWORD=$DB_PASSWORD
EOF
sudo chmod +x /opt/tomcat/bin/setenv.sh
Tomcatは起動時に/opt/tomcat/bin/setenv.shを自動で読み込み、その中でexportした環境変数をJVM(つまりデプロイしたSpring Bootアプリ)に渡します。アプリ側のソースコードにDBパスワードをハードコードせずに済む、実務でもよく使われるパターンです。
2. パスワードはSSM Parameter Storeから取得してそのまま埋め込む
DB_PASSWORD=$(aws ssm get-parameter \
--name "/my/webapp/db-password" \
--query "Parameter.Value" \
--output text \
--region ap-northeast-1 \
--with-decryption)
SecureString型のパラメータは--with-decryptionフラグ付きで取得しないと暗号化されたままの文字列が返ってきます。取得した値をそのままheredocでsetenv.shに埋め込むことで、パスワードをターミナルの操作履歴以外に一切残さずに済みます。
3. WARファイルはSCPでEC2に転送する
scp -i C:\Users\ユーザー名\.ssh\my-webapp-key.pem ^
C:\(プロジェクトフォルダ)\alb-ec2-rds-webapp\app\target\webapp.war ^
ec2-user@(EC2のパブリックIP):/home/ec2-user/
mvn packageでビルドしたwebapp.warを、SSH接続とは別のターミナルからSCPで転送します。ALB経由でアクセスするEC2に対してSCPを使う場合も、送信元は結局EC2のパブリックIPを直接指定する点は変わりません。
4. ROOT.warという名前でデプロイするとルートパスで公開される
sudo rm -rf /opt/tomcat/webapps/ROOT /opt/tomcat/webapps/ROOT.war
sudo cp ~/webapp.war /opt/tomcat/webapps/ROOT.war
sudo /opt/tomcat/bin/startup.sh
Tomcatはwebapps/配下のWARファイル名をそのままコンテキストパスとして扱うため、ROOT.warという名前でデプロイするとアプリがhttp://ホスト名/というパスなしのルートで公開されます。既存のROOT(UserDataで作った静的HTMLの残骸)を先に削除しておかないと、Tomcatの自動展開が正しく動かない点に注意が必要です。
5. デプロイの成否はcatalina.outとcurlで二重に確認する
sudo tail -50 /opt/tomcat/logs/catalina.out
curl -s http://localhost:8080/ | head -5
Server startup in [XXXX] millisecondsのログが出ていても、実際にHTTPレスポンスが正しく返るかはcurlで確認するのが確実です。ALBのヘルスチェックがUnhealthyのまま止まる場合、まずEC2内でこの2つのコマンドを実行して原因を切り分けます。
まとめ
setenv.shによるDB接続情報のJVM注入と、SCP転送→ROOT.war配置というTomcatへの手動デプロイフローが、このハンズオンで最も実務に近い部分でした。パスワードをSecureStringで管理しつつheredocで直接埋め込む流れも、実際のオンプレ〜クラウド移行案件でよく使われるパターンです。
→ AWSコンソールでSpring Boot WebアプリをALB + EC2(Tomcat) + RDS にデプロイする手順(ブログ)