Herokuを使用したDocker + Rails + MySQLアプリのデプロイ
なぜHerokuを利用するのか?
早く手軽に公開するにはHerokuが最適だと考えたため。
今回は既存のアプリをHerokuにデプロイするための備忘録のため、Herokuへの登録、アプリ作成手順などは記述しない。
ローカルの動作環境は以下
補足: Intel BigSur
sw_vers
#=> ProductName: macOS
#=> ProductVersion: 11.7.3
#=> BuildVersion: 20G1116
docker --version
#=> Docker version 20.10.22, build 3a2c30b
docker compose version
#=> Docker Compose version v2.15.1
docker compose run --rm web ruby -v
#=> [+] Running 1/0
#=> ⠿ Container my_app-db-1 Running #=> 0.0s
#=> ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5) [x86_64-linux]
docker compose run --rm web rails -v
#=> [+] Running 1/0
#=> ⠿ Container my_app-db-1 Running #=> 0.0s
#=> Rails 6.1.7.2
Herokuアプリケーションの作成
Herokuにログイン
terminalで以下を実行
# cd path/to/project;
# herokuにログインする
heroku login
# Herokuへコンテナを登録するためにコンテナレジストリにログイン
heroku container:login
Herokuアプリのための環境変数を設定する。
そのためにはまずJAWSDB_URL
なるものを知る必要がある。以下のコマンドで表示される。表示されるURLは分解して環境変数の値としても使用される。
JawsDB MySQL | Heroku Dev Center
# heroku config でも表示される
heroku config:get JAWSDB_URL
#=> JAWSDB_URL: mysql://username:password@hostname:port/default_schema
#=> JAWSDB_URL: mysql://<ユーザー名>:<パスワード>@<ホスト名>:<ポート番号>/<データベース名>
JawsDB MySQL | Heroku Dev Center
HerokuでDocker環境Rails MySQLなものを動かす。deviseかつtwitter APIを隠しながら - Qiita
config/database.yml
をHeroku用に本番環境設定用の記述を編集する。
個人的にはAWSなどの他環境へのデプロイも考えているためconfig/database.heroku.yml
という別ファイルで設定している。
# 省略
production:
<<: *default
database: <%= ENV['HEROKU_DB_DATABASE_NAME'] %>
# 変更
encoding: utf8
host: <%= ENV['HEROKU_DB_HOST'] %>
username: <%= ENV['HEROKU_DB_USERNAME'] %>
password: <%= ENV['HEROKU_DB_PASSWORD'] %>
# 追記
url: <%= ENV['JAWSDB_URL'] %>
上記のconfig/database.yml
を参考に環境変数をterminalで設定すると以下のようになる(GUIで設定することも可能)。変数は適宜修正する必要あり。
# JAWSDB_URL: mysql://username:password@hostname:port/default_schema
heroku config:set HEROKU_DB_DATABASE_NAME='default_schema'
heroku config:set HEROKU_DB_HOST='hostname'
heroku config:set HEROKU_DB_USERNAME='username'
heroku config:set HEROKU_DB_PASSWORD='password'
# mysqlのあとに2をつけるのを忘れないこと!!
heroku config:set JAWSDB_URL='mysql2://username:password@hostname:port/default_schema'
herokuの環境変数を設定してrailsからDBにアクセスする
HerokuでDocker環境Rails MySQLなものを動かす。deviseかつtwitter APIを隠しながら - Qiita
herokuでMySQL5.7以降を使うためにClearDBからJawsDBに変更する - Qiita
heroku config
で上記の設定した値が表示されればok!!
heroku config
# HEROKU_DB_DATABASE_NAME: default_schema
# HEROKU_DB_HOST: hostname
# HEROKU_DB_USERNAME: username
# HEROKU_DB_PASSWORD: password
# JAWSDB_URL: mysql2://username:password@hostname:port/default_schema
RailsプロジェクトにHeroku用の設定を追加する
config/environments/production.rb
以下を追記
# 省略
# config.assets.compile = false
config.assets.compile = true
# config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
config.public_file_server.enabled = true
HerokuでDocker環境Rails MySQLなものを動かす。deviseかつtwitter APIを隠しながら - Qiita
Dockerで環境構築したRailsをHerokuにデプロイする方法-前編
heroku.yml
を追加
build:
docker:
web: Dockerfile.production
release:
command:
- mv confing/environments/production.heroku.rb confing/environments/production.rb
- mv config/database.heroku.yml config/database.yml
- mv config/puma.heroku.rb config/puma.rb
- bundle exec rake db:create RAILS_ENV=production
- bundle exec rake db:migrate RAILS_ENV=production
- bundle exec bin/webpack
run:
web: bundle exec puma -C config/puma.rb
config/puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup if defined?(DefaultRackup)
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
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
Deploying Rails Applications with the Puma Web Server | Heroku Dev Center
heroku.yml解説編。Docker環境のRails6をHerokuにデプロイする(1/2) - 独学プログラマ
config/database.yml
個人的にはAWSなどの他環境へのデプロイも考えているためconfig/database.heroku.yml
という別ファイルで設定している。
# 省略
production:
<<: *default
database: <%= ENV['HEROKU_DB_DATABASE_NAME'] %>
# 変更
encoding: utf8
host: <%= ENV['HEROKU_DB_HOST'] %>
username: <%= ENV['HEROKU_DB_USERNAME'] %>
password: <%= ENV['HEROKU_DB_PASSWORD'] %>
# 追記
url: <%= ENV['JAWSDB_URL'] %>
ローカルからHerokuにデプロイする
Herokuのリモートリポジトリ先は今までの流れで登録されているはず。
もし登録されていない場合は以下を参考に設定する。
HerokuCLI-manifestのデプロイ解説編。Docker環境のRails6をHerokuにデプロイする(2/2) - 独学プログラマ
Herokuへプロジェクトをプッシュする
実行すると以下のような感じのログが表示されるはず(エラーが表示されなければok)
git push heroku main
#=> Enumerating objects: 8, done.
#=> Counting objects: 100% (8/8), done.
#=> Delta compression using up to 4 threads
#=> Compressing objects: 100% (5/5), done.
#=> Writing objects: 100% (5/5), 669 bytes | 669.00 KiB/s, done.
#=> Total 5 (delta 4), reused 0 (delta 0), pack-reused 0
#=> remote: Pushed to branch other than [main, master], skipping build.
#=> To https://git.heroku.com/my_web_app.git
#=> 48a3947..43228ac main -> main
heroku.ymlを使用してHerokuへデプロイする
HerokuCLI-manifestのデプロイ解説編。Docker環境のRails6をHerokuにデプロイする(2/2) - 独学プログラマを参考にすすめようとしたがgit push heroku main
のあとheroku open
を実行してみたが全く反応しない(エラー扱いだった)。
なんでかわからず調べていくとDeploying with Docker | Heroku Dev CenterにDockerを使用したデプロイ方法が公式で書かれていた。手順はContainer Registry & Runtime (Docker Deploys) | Heroku Dev Centerを参考にした。
ここで数時間ハマってしまった...
heroku container:push web
heroku container:release web
heroku open
現在エラーにどハマり中
heroku logs --tail
を実行するとたいてい以下のコマンドで落ちている。
port 3000じゃないの?
2023-02-02T08:03:35.104134+00:00 heroku[web.1]: State changed from crashed to starting
2023-02-02T08:04:02.748572+00:00 heroku[web.1]: Starting process with command `rails server -b 0.0.0.0 -p 3000`
2023-02-02T08:04:12.005785+00:00 app[web.1]: => Booting Puma
2023-02-02T08:04:12.005817+00:00 app[web.1]: => Rails 6.1.7.2 application starting in production
2023-02-02T08:04:12.005817+00:00 app[web.1]: => Run `bin/rails server --help` for more startup options
2023-02-02T08:04:16.313753+00:00 app[web.1]: Puma starting in single mode...
2023-02-02T08:04:16.313852+00:00 app[web.1]: * Puma version: 6.0.2 (ruby 2.7.7-p221) ("Sunflower")
2023-02-02T08:04:16.313888+00:00 app[web.1]: * Min threads: 5
2023-02-02T08:04:16.313911+00:00 app[web.1]: * Max threads: 5
2023-02-02T08:04:16.313957+00:00 app[web.1]: * Environment: production
2023-02-02T08:04:16.313986+00:00 app[web.1]: * PID: 3
2023-02-02T08:04:16.314956+00:00 app[web.1]: * Listening on http://0.0.0.0:3000
2023-02-02T08:04:16.321780+00:00 app[web.1]: Use Ctrl-C to stop
2023-02-02T08:05:03.024669+00:00 heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
2023-02-02T08:05:03.052600+00:00 heroku[web.1]: Stopping process with SIGKILL
2023-02-02T08:05:03.224138+00:00 heroku[web.1]: Process exited with status 137
2023-02-02T08:05:03.272466+00:00 heroku[web.1]: State changed from starting to crashed
とりあえず手順をさらす
参考:
DockerでRailsの環境構築してHerokuへデプロイする - Qiita
- Herokuへプッシュ
git push heroku heroku-main
- 対象プロジェクトのイメージをストップする
docker compose down
- イメージを作成してコンテナレジストリにpush
heroku container:push web
- イメージをherokuへデプロイ
heroku container:release web
- 必要なRailsコマンドを実行
heroku rake db:migrate RAILS_ENV=production;
heroku rake db:seed_fu RAILS_ENV=production;
heroku run bin/webpack;
- 実際にアクセスして表示を確認してみる
heroku open
もしかしたらまったく方法が違ったのかもしれない。
現状としては問題なく動作していそう(git push
を行った時点でデプロイのためのコマンドが走るようになった)
今までの違いはDockerfileの名前を変えたこと。
原因の検討箇所が全く違った。
原因となっていたのは以下などのリンクを参考にしつつ、Heroku公式のドキュメントをベースにして
Herokuの設定をしていたことでした。
Dockerで作成したRailsアプリケーションをHerokuにデプロイする - bagelee(ベーグリー)
RailsアプリをDockerで作ってCircleCIで自動テストしてHerokuにデプロイした話 - Qiita
Dockerfile解説編。Docker環境のNuxt.jsをHerokuにデプロイする(1/2) - 独学プログラマ
特にRailsアプリをDockerで作ってCircleCIで自動テストしてHerokuにデプロイした話 - Qiitaは使用している技術ややりたいこともドンピシャで参考にしました。
参考にした上で公式ドキュメントを読み、設定をしました。
heroku.ymlを使った場合のデプロイ方法の公式ドキュメントのリンクは以下になります。
Building Docker Images with heroku.yml | Heroku Dev Center
単純に上記リンクに従って以下のコードを実行していたことが原因でした。
heroku stack:set container
これをスタック | Heroku Dev Centerに記述されている以下のコードを実行してスタックの設定を変更すると無事アプリケーションが起動しました(したはず)!
heroku stack:set heroku-22 # 22は適宜変更
Herokuのドキュメント、
heroku.yml を使用して Docker イメージをビルドする | Heroku Dev Center
についてもっと詳細に書いてほしかった。
いや、もしかしたらどっかで自分の手順に問題があったのかもしれん...
またHerokuにデプロイする機会があれば再検証してみる。