よくありがちなAWS+Railsでアプリ公開をしていく中でいくつかハマった点があったので、備忘録の意も込めて残します。誰かの参考になれば幸いです。
※ 開発環境の具体的な手順などは別記事を引用し、あくまでアプリ公開までに引っかかったポイントなどを中心的にまとめています。ご了承ください。
#開発環境
- Rails 5.2.4
- Docker 19.03.13-ce
- Nginx 1.18
- Unicorn 5.4.1
- AWS EC2
- AWS RDS(MySQL)
- AWS S3
- AWS CloudFront
#Rails on Docker環境構築
Docker + Railsの参考サイトは山ほどあるので、各々自由に構築してください。
※最低限の動作確認なら公式で問題ないと思います
【参考】 Quickstart: Compose and Rails
#RailsアプリをEC2にデプロイ
こちらの記事を参考にデプロイしました。かなりお世話になった記事です。
【参考】 無料!かつ最短?で Ruby on Rails on Docker on AWS のアプリを公開するぞ。
###★ハマりポイント1★
Webアプリを起動してもアクセスはじかれる問題
上の記事を参考に順調にロードバランサー、セキュリティグループ、ターゲットグループと構築を進めていましたが、ALB経由でのアクセス確認で事件が起きました。
ALBの設定は一通り完了、EC2上でdocker-compose upによるRailsアプリ起動(development)も無問題、だがしかしALB経由でアクセスしようとすると502: Bad gatewayが発生してしまう状態です。
####解決
結論からいうとRails(development)で使用するポート3000が開通されていませんでした。。
下記の記事でそのことに気づけました本当にありがとうございます。
【参考】 AWSにRailsアプリケーションを実行する環境作りの手順メモ
上記問題を解決すると、独自で取得・設定したドメインからWebアプリへアクセスが問題なく確認できました。
#本番環境用にNginx、Unicornを導入
下記を参考にproductionで利用するNginxとUnicornを導入しました。
【参考】 AWS+Nginx+Unicornを利用してRailsアプリをデプロイしてみた。〜その1〜
念のためNginxとUnicornの公式などを読んで理解を深めましたが、特に問題ありませんでした。
#AssetSync + S3 + CloudFrontによる高速配信
Webアプリを高速配信するため、CDNにCloudFront、ストレージにS3を用意しました。
また、Rails(production)のassetsをprecompileしたときにS3へ自動アップロードさせるためAssetSyncを導入しました。こちらの記事を参考にしています。
【参考】 assets on S3の導入
※最低限動作できれば良かったため、capistranoは使用していません。
AssetSyncは下記githubにて、詳細や使用手順がまとめられています。
【参考】 AssetSync/asset_sync: Synchronises Assets between Rails and S3
###★ハマりポイント2★
AssetSyncで自動アップロードできない問題
AssetSyncの設定も一通り終え、いざprecompileしてみると下記エラーが発生してしまいました。
Expected(200) <=> Actual(403 Forbidden)
AssetSyncのgithubでも説明がありますが、このエラーはS3へのアクセス権限がちゃんと設定ができていないときに発生します。(アクセスキーやIAMロールの未設定など)
しかしちゃんとAmazon S3 Full Accessを付与したIAMロールを使用していたのでなぜエラーが出るのか、詰まってしまいました。
####解決
はい。IAMロールに対するバケットポリシーの設定内容が間違っていました。バケットポリシーは正確に設定する必要があるので、みなさん気を付けてください。
###★ハマりポイント3★
時折現れる502: Bad gateway問題
上記まででWebアプリの動作確認が取れてきましたが、Webアプリにアクセスしていると時折502: Bad gatewayが発生して疑問に思っていました。
####解決
CloudFrontのアクセスログをS3へ出力し502エラーの原因を解析しました。
【参考】 CloudFrontのアクセスログ設定方法
解析した結果、ALBのルーティングの際にproductionで使用していないポートへルートされて502が返ってきていたことがわかりました。瞬で使用されていないポートを削除し、なぞの502エラーは解決しました。
###★ハマりポイント4★
ridgepole起動時のMySQL connectエラー問題
RDBS管理にridgepoleを利用していましたが、productionでbundle exec ridgepoleすると下記エラーが発生しました。
[ERROR] Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (111)
####解決
最初はsocketの設定ミスかなと思っていましたが、設定ミスはありませんでした。
検索サイトのほとんどは'/var/lib/mysql/mysql.sock'ファイルの権限誤りやMySQLの設定ミスに関するものばかりで、すべて試してもだめだったので途方に暮れていましたが、下記の記事がすべてを変えてくれました。
【参考】 ridgepole 導入はまりどころ
一部引用
「ridgepole読み込みのタイミングでconfig/database.yml (内のerbから.env見ている部分)が展開されない」
(そんなことあるの...)完全にridgepole勉強不足でした!
dotenv -f ".env"コマンドを追加して無事解決。
#最後に
Rails on AWS(CloudFront)を趣味で実装してみて思った以上につまづきポイントがありましたが、無事安定稼働まで辿り着けて良かったです。
最後までご視聴いただきありがとうございました。