質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Amazon EC2

Amazon EC2は“Amazon Elastic Compute Cloud”の略称です。Amazon Web Services(AWS)の一部であり、仮想化されたWebサーバーのコンピュータリソースをレンタルできるサービスです。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

解決済

[Rails]ブラウザからEC2にアクセスしたときだけMySQLが"...socket '/tmp/mysql.sock' (2)"エラーになるのを解決したい

hajsu00
hajsu00

総合スコア117

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Amazon EC2

Amazon EC2は“Amazon Elastic Compute Cloud”の略称です。Amazon Web Services(AWS)の一部であり、仮想化されたWebサーバーのコンピュータリソースをレンタルできるサービスです。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。

1回答

0評価

1クリップ

326閲覧

投稿2022/05/04 04:43

編集2022/05/06 14:20

AWS初心者です。
RailsアプリをEC2にデプロイしたいのですが、ブラウザでEC2のIPアドレスにアクセスするとMySQLへの接続エラーが発生して解決できずに困っています。

ご助言をいただけると幸いです。

起きている問題

・ブラウザからEC2のIPアドレスにアクセスすると
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
が発生する。
※SSHで直接EC2に入ると、Rails<=>MySQLは正常に動作する(詳細は後述)

前提事項

開発環境

・macOS Monterey v12.1
・ruby v3.0.3
・Rails v6.1.4.4
・MySQL 8.0.28
・puma 5.5.2
・nginx 1.20.0

インフラ構成図

イメージ説明

ディレクトリ構造

directory

my-app ├── src │ ├── app │ ├── bin │ ├── config │ ├── ... │ └── ... ├── .gitattributes ├── .gitignore └── README.md

関係するコード

EC2内でnginxとpumaを起動済み(設定は以下の通り)

# /etc/nginx/conf.d/my_app.conf upstream puma { server unix:/var/www/my_app/src/tmp/sockets/puma.sock; } server { listen 80; server_name ***.***.***.***; keepalive_timeout 0; access_log /var/log/nginx/my_app.access.log main; client_max_body_size 4G; root /var/www/my_app/src/public; location ~ .*\.(swf|SWF|ico|ICO|jar|txt|gz|js) { root /var/www/my_app/src/public; expires 15m; break; } location ~ ^\/fonts\/* { root /var/www/my_app/src/public; expires 15m; break; } location ~ ^\/assets\/* { root /var/www/my_app/src/public; break; } location ~ ^\/favicon\/* { root /var/www/my_app/src/public; break; } location = /manifest.json { root /var/www/my_app/src/public; break; } location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; #auth_basic "Restricted"; #auth_basic_user_file /etc/nginx/.htpasswd; #if ($http_x_forwarded_proto = "http") { #rewrite ^(.*) https://$server_name$1 #break; #} proxy_pass http://puma; } }

ruby

# /var/www/my_app/src/config/puma.rb workers Integer(ENV['WEB_CONCURRENCY'] || 2) max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } threads min_threads_count, max_threads_count preload_app! rackup DefaultRackup # rails_env = ENV.fetch("RAILS_ENV") { "development" } rails_env = "production" environment rails_env bind "unix:///var/www/my_app/src/tmp/sockets/puma.sock" pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } plugin :tmp_restart on_worker_boot do # Worker specific setup for Rails 4.1+ # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot ActiveRecord::Base.establish_connection end

yml

# /var/www/my_app/src/config/database.yml default: &default adapter: mysql2 encoding: utf8mb4 reconnect: false pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: <%= ENV['DATABASE_PASSWORD'] %> host: localhost development: <<: *default database: my_app_development socket: /tmp/mysql.sock test: <<: *default database: my_app_test socket: /tmp/mysql.sock production: database: my_app_production adapter: mysql2 encoding: utf8mb4 charset: utf8mb4 collation: utf8mb4_general_ci username: <%= Rails.application.credentials.db[:user_name] %> password: <%= Rails.application.credentials.db[:password] %> host: <%= Rails.application.credentials.db[:endpoint] %> pool: 20 timeout: 1000 socket: /tmp/mysql.sock

試したこと

rails c内ではEC2<=>RDSの通信に成功していることを確認

bash

[ec2-user@ip-10-0-1-40 src]$ RAILS_ENV=production rails c Loading production environment (Rails 6.1.4.4) irb(main):001:0> User.count => 0

・EC2内のmysql.sockの場所を調べてdatabase.ymlに記載

console

[hajsu00@ip-10-0-1-40 conf.d]$ mysql_config --socket /var/lib/mysql/mysql.sock

yml

# /var/www/my_app/src/config/database.yml default: &default adapter: mysql2 encoding: utf8mb4 reconnect: false pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: <%= ENV['DATABASE_PASSWORD'] %> host: localhost development: <<: *default database: my_app_development socket: /tmp/mysql.sock test: <<: *default database: my_app_test socket: /tmp/mysql.sock production: database: my_app_production adapter: mysql2 encoding: utf8mb4 charset: utf8mb4 collation: utf8mb4_general_ci username: <%= Rails.application.credentials.db[:user_name] %> password: <%= Rails.application.credentials.db[:password] %> host: <%= Rails.application.credentials.db[:endpoint] %> pool: 20 timeout: 1000 # socket: /tmp/mysql.sock socket: /var/lib/mysql/mysql.sock

→エラー文はCan't connect to local MySQL server through socket '/tmp/mysql.sock' (2)で変化なし

考えたこと

ec2内でのRails<=>MySQL通信には成功していること、ブラウザからhttpアクセスには成功している(Railsのエラー場面が表示されている)ことからnginx<=>pumaで問題が発生していると考えています。
しかし、検索しても長時間解決に至りません。

お手数お掛けしますが、ご助言いただけると幸いです。
よろしくお願いします。

追記(5/5)

68user さんのコメントをもとに検証を進めました。

puma.rbを修正

そもそもpuma.rbが間違いだらけでしたので、書き直しました。

まず、上記実行にあたりサーバー内のRails実行環境を改めて指定。
$ export RAILS_ENV=production

次に、puma.rbを以下のように書き換える。

ruby

workers Integer(ENV['WEB_CONCURRENCY'] || 2) max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } threads min_threads_count, max_threads_count preload_app! rails_env = ENV.fetch("RAILS_ENV") { "development" } environment rails_env case rails_env when "development" port ENV.fetch("PORT") { 3000 } when "production" bind "unix:///var/www/hangartalk/src/tmp/sockets/puma.sock" end pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } plugin :tmp_restart on_worker_boot do # Worker specific setup for Rails 4.1+ # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot ActiveRecord::Base.establish_connection end

その結果、おそらくnginxへ接続できていない

$ curl http://localhost | head % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0

EC2内のRails<=>MySQLは失敗していた

database.ymlの設定を以下の2通りで試しました。

yml

production: ... # socket: /tmp/mysql.sock port: 3306

それぞれの場合でEC2内でmysql -u {ユーザー名} -pでログインを試みたところ、表題と同じエラーが出ました。
EC2内でもデータベースへの接続に失敗していたことになります。

EC2 => RDS(MySQL)は成功

EC2内からRDSにエンドポイントを指定してログインを試みたところ、成功しました。
ということは、Rails => RDSが失敗している?

bash

$ mysql -u <ユーザー名> -p -h <RDSのエンドポイント> Enter password: Welcome to the MariaDB monitor. Commands end with ; or \g. Your MySQL connection id is 23 Server version: 8.0.28 Source distribution Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MySQL [(none)]> SHOW DATABASES; +-----------------------+ | Database | +-----------------------+ | myapp_production | | information_schema | | mysql | | performance_schema | | sys | +-----------------------+ 5 rows in set (0.00 sec)

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

68user

2022/05/04 08:08 編集

その環境は production なわけですよね。 Rails で /tmp/mysql.sock 経由で RDS につながっていると判断しているんですよね (ほんとに成功しているのかな? と思いますが Rails よくわからず)。 RDS に接続するには当然 TCP/IP 経由でつながないといけないわけですが、EC2 内に UNIX ドメインソケットである /tmp/mysql.sock を listen し、RDS に中継してくれる proxy がいるってことですか? RDS Proxy とか使っているってことでしょうか? proxy なんていないということであれば、RDS のポート 3306 につなぐように設定し、セキュリティグループで EC2 から RDS に接続を許可する、というのが一般的かと思います。 とりあえず接続試験は mysql コマンドでやってみた方がよいと思います。
hajsu00

2022/05/05 04:00

お返事遅くなり申し訳ありません。 コメントありがとうございます。 まだ検証が終わっていないのですが、現状を本文に追記させていただきました。 まず、実行環境は production であることを再確認しました。 proxyは設置していないので、ご指摘の通りdatabase.ymlのproductionにport: 3306を記載して検証中です。 またpumaの設定が間違っていたのですが、本文中に追記させたいただいた通り、puma.rbの bind "unix:///var/www/hangartalk/src/tmp/sockets/puma.sock" が実行されているため、pumaはmy_app.conf(nginx)の server unix:/var/www/my_app/src/tmp/sockets/puma.sock; をlistenできていると思われますが、nginxに接続失敗しているので調べています。 (参考サイトによる「unix:///」と「unix:/」との使い分けの意味が未だわからず...)
68user

2022/05/05 09:03 編集

rails や puma はわからないのでこれ以上はお役に立てないようですが、全体的に確認方法が甘い気はします。ps でプロセス見てみるとか、lsof や netstat -a で、ポート80 や UNIXドメインソケットを LISTEN しているのかとか、telnet 等で puma に直接接続できるのかとか、curl を使うにしても結果がよくわからんです (接続失敗なのか、それ以外なのか)。あとログファイルになにか出てないでしょうか? 他の方からの回答がないようなら情報追加して別質問を立ててみてはと思います。
hajsu00

2022/05/05 11:22

ありがとうございます。 質問投稿時より状況が変わってきていますので、別質問を立てたいと思います。 ご指摘いただいた確認方法も、ひとつづつ調べていきたいと思います。 ありがとうございました!
yu_1985

2022/05/06 05:20

ローカルファイルの/tmp/mysql.sockをdefaultに含めてしまうとすべての設定でそれを参照してしまうので、defaultではなく必要な環境にだけ個別に設定すべきではないでしょうか。 接続先がRDSならローカルのソケットファイルを参照してしまうとおかしなことになる気がします。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Amazon EC2

Amazon EC2は“Amazon Elastic Compute Cloud”の略称です。Amazon Web Services(AWS)の一部であり、仮想化されたWebサーバーのコンピュータリソースをレンタルできるサービスです。

AWS(Amazon Web Services)

Amazon Web Services (AWS)は、仮想空間を機軸とした、クラスター状のコンピュータ・ネットワーク・データベース・ストーレッジ・サポートツールをAWSというインフラから提供する商用サービスです。