Closed22

Herokuを使用したDocker + Rails + MySQLアプリのデプロイ

ピン留めされたアイテム
fsefasfsefas

なぜHerokuを利用するのか?

早く手軽に公開するにはHerokuが最適だと考えたため。
今回は既存のアプリをHerokuにデプロイするための備忘録のため、Herokuへの登録、アプリ作成手順などは記述しない。

fsefasfsefas

ローカルの動作環境は以下

補足: 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

DockerとDocker composeのバージョン確認方法について - Qiita

fsefasfsefas

Herokuアプリケーションの作成

Herokuにログイン

terminalで以下を実行

# cd path/to/project;
# herokuにログインする
heroku login
# Herokuへコンテナを登録するためにコンテナレジストリにログイン
heroku container:login

Docker初心者がRailsコンテナをHerokuへデプロイしてみる

fsefasfsefas

作成したアプリケーション用のJAWSDB(MySQL, 5.7)を作成。my-db-nameは適宜変更(好きな名前でよいと思う)。
ClearDB の MySQL のバージョンは 5.5系のためJawsDBの方がよい。
またJawsDBのバージョンはMySQL5.7〜8系まで対応しているためバージョン指定しておいた方が良さそう。

heroku addons:create jawsdb:kitefin --name=my-db-name --version=5.7

herokuでMySQL5.7以降を使うためにClearDBからJawsDBに変更する - Qiita

fsefasfsefas

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

fsefasfsefas

config/database.ymlをHeroku用に本番環境設定用の記述を編集する。
個人的にはAWSなどの他環境へのデプロイも考えているためconfig/database.heroku.ymlという別ファイルで設定している。

config/database.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でMySQL5.7以降を使うためにClearDBからJawsDBに変更する - Qiita

fsefasfsefas

上記の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

fsefasfsefas

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
fsefasfsefas

RailsプロジェクトにHeroku用の設定を追加する

config/environments/production.rb

以下を追記

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にデプロイする方法-前編

fsefasfsefas

heroku.ymlを追加

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
fsefasfsefas

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) - 独学プログラマ

fsefasfsefas

config/database.yml

個人的にはAWSなどの他環境へのデプロイも考えているためconfig/database.heroku.ymlという別ファイルで設定している。

config/database.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でMySQL5.7以降を使うためにClearDBからJawsDBに変更する - Qiita

fsefasfsefas

ローカルから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
fsefasfsefas

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
fsefasfsefas

現在エラーにどハマり中
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
fsefasfsefas

とりあえず手順をさらす
参考:
DockerでRailsの環境構築してHerokuへデプロイする - Qiita

  1. Herokuへプッシュ
git push heroku heroku-main
  1. 対象プロジェクトのイメージをストップする
docker compose down
  1. イメージを作成してコンテナレジストリにpush
heroku container:push web
  1. イメージをherokuへデプロイ
heroku container:release web
  1. 必要なRailsコマンドを実行
heroku rake db:migrate RAILS_ENV=production;
heroku rake db:seed_fu RAILS_ENV=production;
heroku run bin/webpack;
  1. 実際にアクセスして表示を確認してみる
heroku open
fsefasfsefas

もしかしたらまったく方法が違ったのかもしれない。
現状としては問題なく動作していそう(git pushを行った時点でデプロイのためのコマンドが走るようになった)
今までの違いはDockerfileの名前を変えたこと。

fsefasfsefas

原因の検討箇所が全く違った。
原因となっていたのは以下などのリンクを参考にしつつ、Heroku公式のドキュメントをベースにしてHerokuの設定をしていたことでした。
Dockerで作成したRailsアプリケーションをHerokuにデプロイする - bagelee(ベーグリー)
RailsアプリをDockerで作ってCircleCIで自動テストしてHerokuにデプロイした話 - Qiita
Dockerfile解説編。Docker環境のNuxt.jsをHerokuにデプロイする(1/2) - 独学プログラマ

特にRailsアプリをDockerで作ってCircleCIで自動テストしてHerokuにデプロイした話 - Qiitaは使用している技術ややりたいこともドンピシャで参考にしました。
参考にした上で公式ドキュメントを読み、設定をしました。

fsefasfsefas

heroku.ymlを使った場合のデプロイ方法の公式ドキュメントのリンクは以下になります。
Building Docker Images with heroku.yml | Heroku Dev Center

単純に上記リンクに従って以下のコードを実行していたことが原因でした。

heroku stack:set container

これをスタック | Heroku Dev Centerに記述されている以下のコードを実行してスタックの設定を変更すると無事アプリケーションが起動しました(したはず)!

heroku stack:set heroku-22 # 22は適宜変更
fsefasfsefas

またHerokuにデプロイする機会があれば再検証してみる。

このスクラップは2023/02/24にクローズされました