はじめに
デプロイの際に遭遇したエラーたちとの奮闘記です。
まとまってませんが、皆さんのエラー解決のヒントになれば幸いです。
Version等
Ruby: 2.3.1
Rails: 5.0.1
AWS(EC2)・Nginx・Unicorn・Mysqlの組み合わせ。
① rails コマンドが使えない
[ec2-user@ip-XXX-XX-XX-XXX teatapp]$ rails secret
-bash: rails: コマンドが見つかりません
解決策
exitで一回ec2を出て入り直すとコマンドが使えるようになる。
なんか変なこと起きたらとりあえず再起動しよう。ド初歩 ...。
② Mysql2::Error: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
「'/tmp/mysql.sock'のソケットじゃ、MySQLと通信できません」とのエラー。アプリケーションが指定しているソケットと、データベース側のソケットが食い違っているために通信ができない模様。
ソケットに関しては以下でざっくり掴めると思います。
IT用語辞典e-Words
「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
$ mysql_config --socket
このコマンドでmysql側のソケットタイプが調べられるので調べてみると、
[ec2-user@ip-XXX-XX-XX-XXX ~]$ mysql_config --socket
/var/lib/mysql/mysql.sock
/var/lib/mysql/mysql.sock
こういうタイプのソケットらしい。
一方、アプリ側のソケットを調べてみると、
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password:
socket: /tmp/mysql.sock
/tmp/mysql.sock
と、Mysql側のソケットとタイプが異なる。
解決策
ということでアプリ側のソケットの記述を以下のように修正。
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password:
socket: /tmp/mysql.sock
(中略)
production:
<<: *default
database: testapp_production
username: testapp
password: <%= ENV['TESTAPP_DATABASE_PASSWORD'] %>
socket: /var/lib/mysql/mysql.sock
default部分の記述は残したままで、productionの方に加筆すればOK。
これで、ソケットタイプが合致してアプリとデータベースが通信できるようになりました。
と、思いきや
③ ERROR -- : Access denied for user 'testapp'@'localhost' (using password: NO) (Mysql2::Error)
[ec2-user@ip-XXX-XX-XX-XXX testapp]$ unicorn_rails -c config/unicorn.rb -E production
のコマンドでunicornを作動しても、うまく立ち上がらず。
何が起こっているのか、エラーの詳細を確認するために、以下のコマンドを実行。
[ec2-user@ip-XXX-XX-XX-XXX testapp]$ less log/unicorn.stderr.log
log/unicorn.stderr.log
のログを辿ると、以下のような記述が。
ERROR -- : Access denied for user 'testapp'@'localhost' (using password: NO) (Mysql2::Error)
using password: NOということで、どうやら環境変数で設定したパスワードが読み込まれていない模様。
①アプリ側の環境変数を読み込んでいるところの記載
②EC2側の環境変数を書き込んでいるところの記載
をチェックしてみると...
production:
<<: *default
database: testapp_production
username: testapp
password: <%= ENV['TESTAPP_DATABASE_PASSWORD'] %>
socket: /var/lib/mysql/mysql.sock
アプリ側は、password: <%= ENV['TESTAPP_DATABASE_PASSWORD'] %>
との記述。
一方EC2側はの記載を以下のコマンドでチェックしてみると、
$ sudo vim /etc/environment
DATABASE_PASSWORD='XXXXXXXXXXXXXXX'
SECRET_KEY_BASE='XXXXXXXXXXXXXXX'
DATABASE_PASSWORD='XXXXXXXXXXXXXXX'
との記述。
変数がアプリ側とEC2側で食い違ってました。
解決策
ということで、アプリ側の記述を以下のように変更。
production:
<<: *default
database: testapp_production
username: testapp
password: <%= ENV['DATABASE_PASSWORD'] %> # 「TESTAPP_」を削除
socket: /var/lib/mysql/mysql.sock
これで環境変数が正しく読み込まれるようになりました。
ちなみにですが、
① Mysqlのroot user passwordの先頭が「0」で始まる場合、環境変数の読み込みがうまくいかない場合がある
② 環境変数名に「-」(ハイフン)を含めると、環境変数の読み込みがうまくいかない場合がある
みたいです。
環境変数を
NEW-APP_DATABASE_PASSWORD='01234567'
SECRET_KEY_BASE='XXXXXXXXXXXXXXX'
のように変数名にハイフンを含めており、パスワードの先頭を0で始めていて、大っ変痛い目に会いました。
ちなみのちなみに、環境変数がちゃんと読み込まれているか確認するには、
[ec2-user@ip-XXX-XX-XX-XXX testapp]$ rails c
でコンソールを開いて、
irb(main):001:0> ENV['DATABASE_PASSWORD']
=> "XXXXXXXX"
と環境変数を打ってあげればちゃんと読み込めているか確認できます。
さて、これでunicornが使えるかと思いきやまたMysqlのエラー。
④ ERROR -- : Access denied for user 'testapp'@'localhost' (using password: YES) (Mysql2::Error)
ソケットも合わせて、
環境変数も読み込めるようにして、
でもエラー。エラー文を見てみると、なんかユーザーのところが「testapp」になっている。ここが原因。
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password:
socket: /tmp/mysql.sock
(中略)
production:
<<: *default
database: testapp_production
password: <%= ENV['TESTAPP_DATABASE_PASSWORD'] %>
# productionのuser部分を削除。
socket: /var/lib/mysql/mysql.sock
解決策
productionのuser部分を削除(するとdefaultのusername、つまりrootがproductionでも読み込まれるようになる)。
これで、
$ unicorn_rails -c config/unicorn.rb -E production
をしてあげるとunicornが立ち上がりました。Mysqlとの通信もうまくいっている模様。でも、
⑤ Unicornは動いているのにページが表示されない
http:// ~Elastic IP~ :3000/でページにアクセスしても、ロードが続くだけで表示されず。
と出てきてしまう。ううう...。
これは原因は単純でポートの開け忘れでした。
AWSでポート3000を開けてあげて、
ページが表示されました。