Posted at

ローカルのRailsコンソールから接続するDBを、一時的に本番DB(DMZ内)に切り替えちゃう

More than 5 years have passed since last update.


やりたいこと

Railsのとっても便利なコンソール。自社のサービス運用をしているところでは、本番のappサーバにsshでログインしてRailsコンソールを開いて、データをチョメチョメすることがありますよね。

でも、こんな不便もあります。


  1. sshでログインしてRailsコンソールを立ち上げるのが面倒

  2. Railsコンソールのリソース消費がサービス運用に影響する

1つ目は screen や byobu を使って回避できるところですが、そうすると2つ目の問題が肥大します。

インフラ管理担当から怒られることもあるでしょう。。

そんな時に「ローカル環境で立ち上げたRailsコンソールから、本番環境のDBを操作できたら便利なんじゃないかなぁ」と思って考えた便利な技です。


前提条件


  • Railsでサービス構築/運用している

  • ローカル環境から本番DBへの接続が可能

DMZ内の本番DBに接続する方法はこれ


手順

以下全てローカル環境です。


database.ymlに本番やステージングDBへの接続を記述しておく

Railsの起動 environment と区別するため、ここではRailsデフォルトで用意されている production ではなく、 honban としています。


database.yml

development:

adapter: mysql2
host: dev.db.server
database: app_name
username: [filtered]
password: [filtered]

test:
adapter: mysql2
host: dev.db.server
database: app_name<%= ENV['TEST_ENV_NUMBER']%>
username: [filtered]
password: [filtered]

# ここ!
honban:
adapter: mysql2
host: 127.0.0.1 # sshトンネリングの設定に合わせています
port: 13306 # sshトンネリングの設定に合わせています
database: app_name_production
username: [filtered]
password: [filtered]



Railsコンソールを立ち上げて(developmentでね)DBを切り換える

$ rails console

[1] pry(main)> # 開発環境DB
[2] pry(main)> User.count
(1.3ms) SELECT COUNT(*) FROM `users` WHERE `users`.`deleted_at` IS NULL
3
[3] pry(main)> # 本番DBに切り換え
[4] pry(main)> ActiveRecord::Base.establish_connection(:honban)
#<ActiveRecord::ConnectionAdapters::ConnectionPool:.......
[5] pry(main)> User.count
(17.0ms) SELECT COUNT(*) FROM `users` WHERE `users`.`deleted_at` IS NULL
343321

ポイントは [4]のこれです。

ActiveRecord::Base.establish_connection(:honban)

Rails.env はあくまでも deveploment のまま、DBだけ切り替えるんです。

切り換えは何度も出来るので、開発環境 > ステージング > 本番 を切り換えながらデータをチェックするなんてことも可能です。


ここが便利ね


development だけに適用しているgemが使える

起動を重くするような gem は、Gemfileで dvelopment, tes のスコープを切って本番環境ではロードしないのが常套かと思います。でもこのやり方だと、 development のみのgemが使えるんです。

上サンプルでも pry を使っているのが分かると思います。hirb も使えちゃいます。


本番環境から(少しだけ)データを持ってくるのが簡単

接続環境を切り替えられるので、こんなことも可能です。

$ rails console

Loading development environment (Rails 3.2.14)

Frame number: 0/4
[1] pry(main)> # 本番環境に接続
[2] pry(main)> ActiveRecord::Base.establish_connection(:honban)
#<ActiveRecord::ConnectionAdapters::ConnectionPool:....
[3] pry(main)> user = User.last
User Load (7.4ms) SELECT `users`.* FROM `users` WHERE ......
+----+------------+------------+.....
| id | email | encrypt... |
+----+------------+------------+.....
| 51 | hoge@ex... | $2a$10$... |
+----+------------+------------+.....
1 row in set
[4] pry(main)> copied_user = user.dup
+------------+------------+----------
| email | encrypt... | reset_pa.
+------------+------------+----------
| hoge@ex... | $2a$10$... |
+------------+------------+----------
1 row in set
[5] pry(main)> # 開発環境に接続し直し
[6] pry(main)> ActiveRecord::Base.establish_connection(:development)
#<ActiveRecord::ConnectionAdapters::ConnectionPool:....
[7] pry(main)> copied_user.save validate:false #開発環境に保存
(1.3ms) BEGIN
SQL (2.2ms) INSERT INTO `users` (`........
(2.9ms) COMMIT
true

※データの転送量を考えてちょっとずつ分けてやりましょーね。