はじめに
個人開発したアプリケーションをAWS EC2で本番環境にデプロイをしました。その後、追加機能としてチャットルーム機能を実装。roomsテーブルを追加しました。
なので再びEC2にデプロイ。
EC2本番環境で新しい機能、rooms/newページでチャットルーム作成をして、rooms/createのページアクセスすると以下のエラーが発生。
room/createのページにアクセスできませんでした。(チャットルームが作成できない状況)
ポイントとして
・開発環境(localhost:3000)とherokuでは問題なくrooms/newからrooms/createにアクセスできる。でもEC2ではできない。
ということ。
今回の原因として、roomsテーブル作成後、新しくnameカラムを追加しました。
結果、そのカラム追加方法に原因があったようです。
そのためEC2のDBにnameカラム反映されなかったみたいでした。内容を詳しく後述します。
まず、使用している開発環境及び追加したテーブル&カラムは以下の通りです。
開発環境
Ruby 2.6.5 Ruby on Rails 6.0.3.7 MySQL 5.6.51 Github 2.30.1 heroku 7.54.0 AWS EC2自動デプロイツール : Capistrano
Webサーバー : nginx
APサーバー :Unicorn
追加したテーブル
rooms
Column | Type | Options |
---|---|---|
name | strings | null: false |
has_many: users through: :room_users
has_many: room_users
room_users(中間テーブル)
Column | Type | Options |
---|---|---|
room | references | foreign_key: true |
user | references | foreign_key: true |
has_many: users
has_many: rooms
新しくテーブル、そのあとにカラムを追加後、EC2上に再度デプロイ。本番環境でチャットルーム新規作成ページにてルームを作成しようとすると、
と表示されてしまった。
このエラーを解決するのに丸一日以上費やしたので、今後のためにも解決した方法をこの記事に載せることにしました。
やっかいだったのが、AWSの情報ってググってもまだ情報量が少ないので答えになかなか辿り着けませんでした。
そこで僕は、エラー解決でどうしようもないときたまにお世話になっている、MENTAを使うことにしました。
原因
EC2上でtail -f production.log
でログを調べると
ActiveModel::UnknownAttributeError in RoomsController#create
unknown attribute 'name' for Room.
ログの中にこいつが見つかりました。前述しましたがこれが今回の原因です。
nameカラムがEC2上のデータベースにないですよ、という意味。
試したこと
まず、試したこととして、以下のコマンドで、Nginxの読み直しと再起動をしました。sudo systemctl reload nginx
sudo systemctl restart nginx
その後、以下のコマンドで、プロセスを確認。
ps aux | grep unicorn
kill プロセス番号
でプロセスをkillしました。
再度デプロイしてみます。
bundle exec cap production deploy
前述しましたが、ググってもAWSの情報はまだ少ないので、解決方法になかなか辿り着けませんでした。
メンターからのアドバイス
そこで今回、MENTAでお願いをしたメンターより、以下のアドバイスをいただきました。
「もし、nameカラムを追加したマイグレーションファイルが一番直近のものでかつロールバック可能であればロールバックして再度マイグレーションを適用するのがいいと思います。
一番簡単なのは一度データベースを作り直すことです。ただし、データが消えるのでデータが消えてもいい場合のみです。」
「基本的にデータベースのロールバックというのはやらない方がいいです。
これをやっていいのは開発環境くらいで本番環境では常にマイグレーションファイルを追加する運用が最も安全かと思います。」
僕は、nameカラムはマイグレーションファイル作成後、必要だと気づいたので、
①roomのマイグレーションファイルをrails db:rollbackでdownさせ
②downさせたマイグレーションファイルにnameカラムを追記
③再びrails db:migrate
→結果これが良くなかったことだったと判明
=次回からは、カラム追加時は新しくマイグレーションファイルを別で作成するようにします!
解決方法手順
本場環境のデータベースを作り直すのであれば下記の方法で作り直せます。DISABLE_DATABASE_ENVIRONMENT_CHECK=1 ./bin/rake db:drop
./bin/rake db:create
./bin/rake db:migrate
しかしコマンド実行後、以下のエラーメッセージが出力
エラー内容
FATAL: Listen error: unable to monitor directories for changes.
Visit https://github.com/guard/listen/wiki/Increasing-the-amount-of-inotify-watchers for info on how to fix this.
ディレクトリの変更を監視することができませんという意味らしい…
エラーの原因
railsコンソールが起動できなかったのは、1つの実ユーザIDに対して生成できるinotifyのインスタンスの数の上限が決まっており、その上限に達してしまった為とのことです。 ここで、inotifyとはLinuxファイルやディレクトリのイベントを監視する機能です。(参考URL: https://qiita.com/yn-misaki/items/c850a07f7858437e4d26)
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
再度試すも、
ターミナルで出たエラー内容
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
Couldn't drop database 'original35700_development'
rake aborted!
Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
-e:1:in `<main>'
Tasks: TOP => db:drop:_unsafe
というエラーが表示
MySQLに繋げられていないようでした。
メンターから以下のコマンドを実行するよう指示。
RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 ./bin/rake db:drop
メンターから「既に削除できているっぽいので下記のコマンドを実行してください。」 とのこと
RAILS_ENV=production ./bin/rake db:create
RAILS_ENV=production ./bin/rake db:migrate
この2つのコマンドを実行し、再度EC2上にデプロイしたところ新たにEC2上でDBが反映され解決!
開発環境でテーブル作成後、あとからカラムを追加するときはrollbackではなく、addでマイグレーションファイルを新たに作成し追加するようにしましょう。