はじめに
今回、PostgreSQLを AWS RDSに用意したものを、Dockerコンテナ内のRails APIから接続するところでかなり詰まったため、解決までの手順をまとめます。
前提
- Rails API モード
- Docker / docker-compose を使用
- DB は AWS RDS(PostgreSQL)
- ローカル PostgreSQL は使用しない
手順1: AWS RDS の作成
ここは前回実施したのでスキップ。
手順2:RDS のセキュリティグループ設定
AWS RDS内で、RDSのセキュリティグループのインバウンドルールを変更。
ソースを0.0.0.0/0にすることでどこからでもアクセスできるようになる。こうすることで開発中の手間が軽くなる。
※本番では絶対に絞ること
インバウンドとアウトバウンド、ファイヤウォールなどについてはこちらの記事がわかりやすかったです。
手順3:.envを作成
プロジェクト直下に.env を作成。
DB_HOST=xxxxxx.xxxxxx.ap-northeast-1.rds.amazonaws.com
DB_USERNAME=(RDSのマスターユーザー名)
DB_PASSWORD=(RDSのマスターパスワード)
.envファイルにパスワードなどの機密情報をまとめ、.gitignoreに設定することで、パスワードをGitに書かずに済み、セキュリティを上げることができる。
詳しくはこちら、
手順4:docker-compose.ymlを設定
.env をそのまま置くだけではDocker コンテナには渡らないため、- .envで明示的に読み込む。
services:
api:
environment:
RAILS_ENV: development
env_file:
- .env
- 確認
これでRDS のエンドポイントが表示されれば接続完了。
docker compose exec api bash echo $DB_HOST
手順3:database.yml を設定
まず、config/database.ymlを以下のように編集
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: <%= ENV["DB_HOST"] %>
port: 5432
username: <%= ENV["DB_USERNAME"] %>
password: <%= ENV["DB_PASSWORD"] %>
development:
<<: *default
database: bible_development
test:
<<: *default
database: bible_test
[今回変更した箇所]
- host: <%= ENV["DB_HOST"] %>
接続先のDBサーバーを設定。
今回はセキュリティ上、AWS RDSのエンドポイントを.envから読み込ませる仕組みに。 - port: 5432
PostgreSQL のデフォルトポート - DBに接続する ユーザー名 / パスワードの設定
これも、
username: <%= ENV["DB_USERNAME"] %> password: <%= ENV["DB_PASSWORD"] %>.envに書いた値を参照している
手順4:Docker再起動、DB作成を実行
.envやdatabase.ymlを変更したら必ず再起動。
docker compose down
docker compose up --build
DB作成を実行し、マイグレーションを実行
docker compose exec api rails db:create
docker compose exec api rails db:migrate
DB作成時に発生したエラー
DB作成時に、このようなエラーが発生した。
no pg_hba.conf entry ... no encryption
[原因]
RDSがSSL接続必須だったのに対し、Railsが平文(非SSL)で返していたことが原因だった。
Rails(pg gem)はデフォルトではSSLでも平文でもOKなら平文で行くという設定らしい。
[対策]
database.ymlの default に以下を追加。
sslmode: require
再度DB作成を実行し、エラー解消。
終わりに
Docker × Rails × AWS RDS の接続は一つ一つは小さい設定でも、順番を間違えると原因が見えにくくなります。
同じ構成で詰まっている方の参考になれば幸いです。
