http://denkinovel.com/ をずっとさくらVPSで動かしていたが、たまになぜか異常にレスポンスが遅い、記憶力の減退からさくらVPSでのサーバーの管理ができなくなってきた、などの理由でAWSに移転した。
AWSをインターンシップでよく使うようになったので、勉強がてら AWS Elastic Beanstalk + RDS の構成にした。
構成
- Rails v4.2.10
- Puma v3.11.4
- PostgreSQL RDS が用意してくれるやつ
- Ruby 2.5.1-p57
DB dump => restore
VPSの旧サーバーの PostgreSQL に入っていたデータを pg_dump で取ってくる。
$ pg_dump -U myapp -Fc myapp_production > myapp_production_db.dump
で、ダンプしたデータを、 AWS RDS で読み込む。
$ pg_restore -h aaaaaa.bbbbbbbb.us-west-1.rds.amazonaws.com -p 5432 -d myapp_production -U myapp myapp_production_db.dump
このへんは公式ドキュメントを読んだらわかる。 https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.Procedural.Importing.html
ただなぜかデータ移行とデプロイ後に (ActionView::Template::Error) "Unknown primary key for table collections in model xxx" のエラーが Rails で発生するようになった。
調べたところ、この人たちが似たような問題を抱えていた。 https://stackoverflow.com/questions/18056162/getting-unknown-primary-key-for-table-while-the-id-is-there
Rails ではデフォルトで primary_key は id のはずなのだが、なぜかそれが設定されていない?
class User < ActiveRecord::Base
self.primary_key = :id
考えるのが面倒になったので、こんな感じに、各 ActiveRecord::Base 継承クラスに self.primary_key = :id
と明示的につけたところ、動いた。
デプロイ
Elastic Beanstalk はリポジトリのサイズ512MB までしか扱えない。 Denkinovel はサービスの性質上、大量の画像と音楽ファイルをリポジトリ内に持っていた。このままではデプロイできない!
そこで、 asset_sync を使って手元の開発機 MacBookPro で rake assets:precompile
をしてしまうことで assets を S3 にアップロードしたうえで、本番環境のサーバにはアップロードしないようにした。本番環境では assets へのアクセスはすべて S3 (CloudFront を使うので実際はCloudFront)に向くので本番環境に assets がなくても問題ない。ただし、 public/assets/.sprockets-*-manifest.json
だけは本番環境にアップロードしておかないといけない。もし public/assets/.sprockets-*-manifest.json
がないと production 環境で Rails が asset_url などを変換する際に /assets/xx.jpg
などではなく /images/xx.jpg
に変換してしまい、ファイルが見つからくなってしまう。
具体的には以下のことをした。
.gitignore で public 内の public/assets/.sprockets-*-manifest.json
以外のファイルをすべて無視する。
public/assets/*
!public/assets/.sprockets-manifest-*.json
app/assets/audios/*
app/assets/images/*
asset_sync
を使い、手元で precompile して S3 に assets はすべてアップロードする
$ RAILS_ENV=production bundle exec rake assets:precompile
これで public/assets に画像や音楽ファイルがプリコンパイルされて入るが、 git はそれを管理しない。ただし .sprockets-manifest-*.json だけは git が管理しているので、その差分は git commit する必要がある。
$ git add .
$ git commit
で、 git に .sprockets-manifest-*.json を記録させたあと
$ eb deploy
でデプロイするようにした。
思ったこと
もう Rails 使うのやだ。