AWSの無料枠が使える期限が差し迫っていること、今後は別アプリに力を入れたいのでAWSにアップしているRailsアプリを停止することにしてHerokuに移行することにしました。
AWSからHerokuに移行している参考になりそうな以下の記事があったのですぐできるかと思ったのですが、数日費やすことになってしまったので備忘録としてのこします(全体の流れとしてはとてもわかりやすいです)。
【Rails + MySQL】AWS→herokuの移行 – blog.aiandrox
HerokuにMySQL+NginxのRailsアプリを移管した - kumamotone’s blog
Dockerを使用しない場合でも同じような手順で使える部分があるとは思いますが参考程度に留めていただきますようお願いいたします。
動作環境
- MacOS
- Rails(6.0.4.1、gem
dotenv-rails
を使用して環境変数管理) - Ruby(2.7.3)
- MySQL(5.7系)
- Docker(20.10.12)
- docker-compose(2.2.3)
移行に際して関連してくるAWSサービス
- EC2
- RDS
- S3
前提
- AWS環境にRailsアプリがあること
- RDSにデータを格納していること(MySQL)
- Herokuの登録、ログインができていること
- EC2へSSH接続できること
今回しないこと
- Heroku, AWSの詳細な説明
- HerokuにNginxをデプロイ
- 独自ドメインを使用
- S3からcloudinaryへの画像の移行
以下のリンクに移行方法が書いてありますが今回は触れません(登録してあるデータ量が少なかったので手作業でやりました)。
Railsで運用しているサービスの画像配信をAWSスタックからCloudinaryに移行した話 | スペースマーケットブログ
手順
1. RDSのデータのバックアップファイルを作成
AWSで動作していた生データをHerokuに移行するためにバックアップファイルを作成します。
1-1. EC2でSSHログイン
RDSに接続するためにEC2にログインします。
ssh -i "鍵ファイル(aaa.pem)" ec2-user@www.xxx.yyy.zzz
以下を参考にしています
[初心者向け] 初めてのEC2ログイン:Linux編 | DevelopersIO
1-2. RDSデータのバックアップファイルを作成する
EC2上で以下のコマンドを実行します。
mysqldump -u ユーザー名 -h ホスト名 -p データベース名 > dump.sql
dump.sql
のファイル名はお好きな名前で大丈夫です。
ファイルが作成されたこと、どこにファイルがあるかを確認します()。
2. バックアップファイルをlocal(Mac)にコピー
AWSのEC2上からlocalにdump.sql
ファイルをコピーするために以下のコマンドを実行します
scp -i "鍵ファイル(aaa.pem)" ec2-user@www.xxx.yyy.zzz:EC2上のdump.sqlまでのファイルパス localの保存したい場所のパス
#=> 例) scp -i "aws-key.pem" username@1.1.1.1:/var/www/hashlog/dump.sql ~/Desktop
scpコマンドに関しては以下のリンクがわかりやすいです。
scpコマンドでサーバー上のファイルorディレクトリをローカルに落としてくる - Qiita
sshでファイル転送の手順 - Qiita
以下は実際にEC2からmysqlのバックアップデータを作成、コピーしている記事です。
RDSのdumpファイルを取得してlocalのMySQLに反映させる | すな.dev
3. Herokuにアップロードするための前準備
3-1. Herokuにterminalでログイン、アプリを作成する
以下のリンクを参考にします。
【Rails7】DockerでRuby on Railsアプリを構築してHerokuにデプロイするまで
冒頭の記事を参考にMySQLデータベースはHeroku上ではJawsDBを使用しました。
【Rails + MySQL】AWS→herokuの移行 – blog.aiandrox
# heroku-cliのインストール
brew tap heroku/brew && brew install heroku
# herokuのコンテナレジストリにログイン
heroku container:login
# herokuアプリを作成 (アプリ名を引数につければ指定したアプリ名で作成できる)
heroku create
3-2. MySQL用のアドオンを追加
# MySQL5.7用のアドオンを追加
heroku addons:create jawsdb:kitefin --version=5.7
以下コマンドでアドオンが追加されているか確認できます。
heroku addons
#=> Add-on Plan Price State
#=> ─────────────────────────────── ─────── ───── ───────
#=> jawsdb (jawsdb-amorphous-40408) kitefin free created
#=> └─ as JAWSDB
3-3. 必要な環境変数を JAWSDB_URL
の値にしたがってHerokuにセットする
3-2でHerokuでMySQL(JawsDB)用のアドオンを追加できたので、Heroku上の環境変数の値を以下のコマンドで確認します。
heroku config
# 現状だと以下のような感じで表示されるはず(他に値は表示されないはず)
# JawsDBのアドオンが追加できていなければ表示されない
# => JAWSDB_URL=mysql://NEWUSER:NEWPASS@NEWHOST:3306/NEWDATABASE
RailsでMySQLを使用している場合は上記のJAWSDB_URL
の値を一部だけ変えなければいけません。
具体的にはmysql
をmysql2
に変更します。
以下のコマンドでJAWSDB_URL
の値を変更できます。
※ config:set
はconfig:add
でも良いかもしれません。
ちなみに間違えて設定した環境変数の値は、terminalheroku config:unset 環境変数名
で削除できます
heroku config:set JAWSDB_URL=mysql2://NEWUSER:NEWPASS@NEWHOST:3306/NEWDATABASE
# JAWSDB_URL=mysql://NEWUSER:NEWPASS@NEWHOST:3306/NEWDATABASE を参考にすると
heroku config:set DATABASE_NAME="*************" # NEWDATABASE の値を代入
heroku config:set DATABASE_PASSWORD="****************" # NEWPASS の値を代入
heroku config:set DATABASE_USERNAME="***************" # NEWUSER の値を代入
人によっては以下の値を設定する場合もある感じです。自分の環境に合わせて設定をします。
heroku configファイルの確認が参考になりそうです。
- LANG
- RACK_ENV
- RAILS_ENV
- RAILS_LOG_TO_STDOUT
- RAILS_SERVE_STATIC_FILES
- SECRET_KEY_BASE
3-4. Herokuで使用した環境変数の値をRails側で参照できるようにする
config/database.yml
の各値はHerokuが発行するデータベース用のURLから分割して割り当て、変更する必要があります。
3-3 まででHerokuの環境変数に値は設定できているのであとはRails側に設定を反映させます。
設定するファイルはconfig/database.yml
です。
# Heroku configで表示される JAWSDB_URL の値との対応ができているか確認しながら設定
production:
<<: *default
database: <%= ENV['DATABASE_NAME'] %>
username: <%= ENV['DATABASE_USERNAME'] %>
password: <%= ENV['DATABASE_PASSWORD'] %>
url: <%= ENV['JAWSDB_URL'] %>
4. Herokuにアップロード
全然知らなかったのですが、Dockerで作成したRailsアプリをHerokuにデプロイするには以下の2通りのやり方があるようです。
どちらもlocalのterminalで何回かコマンドを打ち込む必要があります。
- Container Registry & Runtime (Docker Deploys) | Heroku Dev Center
- Building Docker Images with heroku.yml | Heroku Dev Center
1つ目のデプロイに関しては以下が参考になりそうです。
DockerでRailsの環境構築してHerokuへデプロイする - Qiita
私の場合は2個目のやり方に従いheroku.yml
を作成してデプロイしました。
build:
docker:
web: Dockerfile.production # 本番用のDockerfile
run:
web: bundle exec puma -C config/puma.rb
terminalで以下のコマンドを実行してデプロイ
# Herokuデプロイ用のブランチを作成
git checkout -b 'heroku_main'
# 変更をcommitする
git add .
git commit -m "Add heroku.yml"
# Herokuのコンテナにスタックをセット
heroku stack:set container
# Herokuにpush
git push heroku heroku_main:main
# DBをdb:migrate
heroku run rails db:migrate
# ブラウザで動作確認
heroku open
5. エラー解決
ただ私の場合、Herokuにアップロードしたあとheroku open
コマンドを実行してアプリして動作確認しましたが、以下のエラーが発生してherokuのエラー画面が表示されました。
Webpacker::Manifest::MissingEntryError
以下にかなりいろいろな対処法が記載されていましたが、私の場合は解決に至りませんでした。
herokuへデプロイする際のWebpaker::Manifest::MissingEntryErrorというエラーの対処法まとめ - Qiita
最終的にはlocalでdocker-composeコマンドを使用して以下のコマンドを実行し、
rails webpacker:compile
- `rails assets:precompile``
.gitignore
の以下のフォルダの記述を削除してコンパイルされているファイルをgit add, commitして再度4 のやりかたでHerokuへアップすることでアプリが動作するようになりました。
-
/public/assets
フォルダ -
/public/packs
フォルダ
6. バックアップファイルのデータをDB(JawsDB)にインポートする
最後です。
以下のコマンドをlocalのterminalで実行してlocalのバックアップファイルからJawsDBにデータをインポートします。
JawsDB MySQL | Heroku Dev Center
mysql -h NEWHOST -u NEWUSER -pNEWPASS NEWDATABASE < dump.sql
注意点ですが、-p
の後にスペースは入れずにコマンドを実行してください。エラー扱いになってしまいます(ややこしい)。
Unable To Migrate .SQL File to JawsDb (MySQL) - Stack Overflow
実行完了までしばらく時間がかかります。Warning: Using a password on the command line interface can be insecure
が表示されたら正常にコマンドが実行できているはずです。そのまま完了するまで待ちましょう。
7. 完了
heroku open
などで該当アプリにアクセスして期待通りの表示がされていればOKです。
お疲れ様でした。