1
Help us understand the problem. What are the problem?

posted at

updated at

Herokuデプロイ奮闘記(前編)

これは、度重なるエラーに苦戦しながらも初めてのHerokuデプロイに成功した、ある一人の男の物語である。

結論(デプロイまでの過程)

  1. Rubyの3.0.1をインストールしてバージョン変更。
  2. 更にRubyの2.7.3をインストールしてもう一度バージョン変更。Bundlerの2.2.17をインストールしてこっちもバージョン変更。
  3. 更にBundlerの2.2.16をインストールしてこっちももう一度バージョン変更(Heroku環境に合わせるため)。このバージョンでbundle install
  4. BundlerをPCの環境に合わせるために、コマンドbundle lock --add-platform x86_64-linuxを実行。
  5. devisekaminariの各Gemを開発・テスト・本番の全ての環境で使えるようにする。
  6. config/environments/production.rbconfig.assets.js_compressor = :uglifierの行をコメントアウトして、テンプレートリテラルを認識させる。
  7. app/assets/stylesheets/style.scss先頭の@import compass;をコメントアウト。
  8. app/assets/stylesheets/style.scss先頭の@import compass;のコメントを外して(元に戻して)、Gemのcompass-railsを開発・テスト・本番の全ての環境で使えるようにする。
  9. デプロイ完了!!

※今回も長くなりそう(なった)なので、前半と後半に記事を分けて書きます。

前提条件

  • macOS Catalina ( 10.15.71 )
  • Rails ( 5.2.61 )
  • Terminal.app ( 2.101 )
  • Ruby ( 2.5.12 )
  • Bundler ( 2.1.42 )
  • Google Chrome.app( 91.0.4472.771 )

本題

1. Rubyのバージョンを変更する

コマンドgit push heroku masterを実行してデプロイ終わったと思いきや...

terminal.app
remote:  !
remote:  !     The Ruby version you are trying to install does not exist on this stack.
remote:  !
remote:  !     You are trying to install ruby-2.5.1 on heroku-20.
remote:  !

これが最初のエラーだった。この下には更に

terminal.app
remote:  !     Ruby ruby-2.5.1 is present on the following stacks:
remote:  !     
remote:  !     - cedar-14
remote:  !     - heroku-16
remote:  !     - heroku-18
remote:  !     
remote:  !     Heroku recommends you use the latest supported Ruby version listed here:
remote:  !     https://devcenter.heroku.com/articles/ruby-support#supported-runtimes
remote:  !     

(以下略)

とメッセージが続いている。このエラーの解決策は、
 1. Rubyを対応しているバージョンに合わせる。
 2. Herokuのstackを下げる。
の2パターンあるが、後者はセキュリティやパフォーマンスの面で悪影響を及ぼす可能性があるらしいので、今回は省略(一応、上記のいずれかのstackに合わせれば解決はできるようだ)。というか、そもそもこのstackとは何ぞや..?こちらの日本語の公式サイトによれば、

スタック​は、Heroku によってキュレートおよび維持されているオペレーティングシステムイメージです。 スタックは通常、Ubuntu などの既存のオープンソースの Linux ディストリビューションに基づいています。Heroku のアプリケーションは特定のスタックを対象とし、​buildpack​ は、あるアプリのソースコードを、そのスタックと互換性がある実行可能パッケージに変換する役目を担っています。

と記述されているが、正直よく分からない...Heroku用のOSといったところか。
さて、Rubyのバージョンを変えなければいけないのだが、上記エラーメッセージに記載されているURLページに飛ぶと、以下のように記述されている箇所がある。

MRI3:

  • 2.6.7, Rubygems: 3.0.3.1
  • 2.7.3, Rubygems: 3.1.6
  • 3.0.1, Rubygems: 3.2.15

この左側の各バージョン値からいずれかを選べば良さそうだ。ここではとりあえずあまり深く考えずに、最も新しいRuby3.0.1をインストールすることにした。

terminal.app
念の為にホームディレクトリに移動して作業する
% cd ~

インストール出来るRubyのバージョン一覧を確認
% rbenv install --list

それぞれの環境にもよるが、一度上を実行すると、2.6.72.7.33.0.1も全部一覧に無い事が分かった。こういう時は、ruby-buildを最新版にアップデートする必要がある

terminal.app
ついでにHomebrewもアップデート
% brew update

ruby-buildをアップデート
% brew upgrade ruby-build

再度バージョン一覧を確認
% rbenv install --list

すると、今度は2.6.72.7.33.0.1が3つ共きちんと表示された。同時に初めのrbenv install --listを実行した時のバージョンが全て消え失せてしまったのが謎なのだが、何はともあれこれで3.0.1をインストールする事ができるようになった。Rubyのインストールは環境構築ぶりだから少しドキドキする...

terminal.app
Rubyの3.0.1をインストール
% rbenv install 3.0.1

リストの中に3.0.1があるのを確認
% rbenv versions

今回はRubyの3.0.1を全体で採用
% rbenv global 3.0.1

バージョンを切り替えたので変更を反映
% rbenv rehash

バージョンが3.0.1に切り替わっているのを確認
% ruby -v

次に、.ruby_versionGemfileのRubyのバージョンも3.0.1に変更する。

.ruby_version
- 2.5.1
+ 3.0.1
Gemfile
- ruby '2.5.1'
+ ruby '3.0.1'

最後に、bundle install4し直せば終了。

terminal.app
デプロイ対象アプリのあるディレクトリに戻る
% cd “アプリのディレクトリ”

Rubyの2.5.1で生成されていたGemfile.lockを一旦削除
% rm gemfile.lock

Gemfile.lockをRubyバージョン3.0.1で再生成
% bundle install

再生成されたGemfile.lockに記載されているRUBY VERSIONと一致しているのを確認
% ruby -v

2. Rubyのバージョンを再度変更し、Bundlerのバージョンも変更する

ここで僕は、ある一つの疑問を抱いた。「これでもしデプロイできたとしても、ローカルで動かせなかったら意味なくね??」。早速rails sをやってみた。すると...

terminal.app
`initialize': wrong number of arguments (given 3, expected 2) (ArgumentError)

サーバーが起動しなかった。案の定、エラーが発生した。上は、そのメッセージの一部分である。
ArgumentErrorとはすなわち引数エラー。「引数の数が違う」という訳で、この下に対象となるファイルであろうパスがズラーッと羅列表示されたが、どこをどう直せば良いのかサッパリ分からない...ググってもなかなか解決策が見つからずに困惑していたところ、或る一つの記事に辿り着いた。詳細は不明だが、後方互換性に影響を及ぼすかもしれないとのこと。憶測ながらも「これが原因なんじゃないかなぁ..」と思い、Rubyのバージョンを下げることに決定。2.7.3をインストールする。その前に、念の為にバージョン2.5.1に戻して再度rails sしてみた。ローカルサーバーは問題なく起動した。やはり、いきなり最新版にバージョンアップしたのが宜しくなかったか...
step.1の流れに沿って、2.7.3をインストールする。bundle installまで終わらせると、文頭に以下のようなメッセージが出力された。

terminal.app
Warning: the running version of Bundler (2.1.4) is older than the version that created the lockfile (2.2.16). We suggest you to upgrade to the version that created the lockfile by running `gem install bundler:2.2.16`.

なるほど、Bundlerも更新させたほうが良さそうだ。その前に、もう一度このバージョンでrails sを実行する。今回は上のような引数エラー等は一切発生せず、ちゃんとlocalhost:3000用のページもブラウザで表示された。まずは一安心...。
Rubyのバージョンは2.7.3でいい感じなので、続いてBundlerのバージョンを変更する。

terminal.app
念の為にホームディレクトリに移動して作業する
% cd ~

最新のBundlerをインストールする
% gem update bundler

インストールされているバージョンの種類が増えているのを確認
% gem list bundler

現行最新版の2.2.17に切り替わっているのを確認
% bundler -v

デプロイ対象アプリのあるディレクトリに戻る
% cd “アプリのディレクトリ”

Bundlerの2.2.16で生成されていたGemfile.lockを一旦削除
% rm gemfile.lock

Gemfile.lockを再生成
% bundle install

ヨシ、これでうまくいった!...と思ったのも束の間、何だか様子がおかしい...カレントディレクトリでgem list bundlerすると

terminal.app
*** LOCAL GEMS ***

bundler (default: 2.1.4)

更にbundler -vしてみても

terminal.app
Bundler version 2.1.4

あれれ〜?変わってないぞぉ〜??しかし、なのにも関わらず、直訳すると「2.1.4はもう古いやんけ!バージョンアップしましょうよ」なる上の警告メッセージが今回はなぜか消えてしまっていた。これは一体どういうことなのだろうか...?
それもそのはずである。2.2.17がインストールされた事になってないのに一度Gemfile.lockを削除した後にbundle installしてしまえば、デフォルトの2.1.4として再生成されるのは至極当然。ではなぜホームディレクトリでインストールしたBundlerの2.2.17が適用されなかったのだろうか?(念の為とは一体...)
こちらの記事によると、2.7系列のRubyだとBundler関連で謎の挙動を示す」的なことが述べられているのだが、今回の原因は別のところにある気がしてならない。というか、単純にホームディレクトリで導入したBundlerのパスを対象ディレクトリへ通してないから適用できてないだけのような...その方法がよく分からないので、今回はこのディレクトリ上でもう一度2.2.17版をインストールして誤魔化す事にした。

terminal.app
現行最新版が2.2.17である事が既に判明しているので、バージョン指定してアプリのディレクトリで再度インストール
% gem install bundler:2.2.17

インストールされているバージョンの種類が増えているのを確認
% gem list bundler

Bundlerの2.1.4で生成されていたGemfile.lockを一旦削除
% rm gemfile.lock

Gemfile.lockを再生成
% bundle install

再生成されたGemfile.lockに記載されているBUNDLED WITHと一致しているのを確認
% bundler -v

3. BundlerのバージョンをHeroku環境に合わせるために再度変更する

ここまででようやく最初のエラーを解決できたので、コミット後にもう一度デプロイしてみる。

terminal.app
ログインしてなかったらログインする
% heroku login --interactive

コードの全修正をインデックスに追加
% git add .

Let's commit!
% git commit -m “コミットメッセージ”

デプロイリベンジ
% git push heroku master 

今度はどうだ!...

terminal.app
remote:  !     Failed to install gems via Bundler.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed

はい、またエラーでーす。がっかり...。しかし、このエラーはこちらの方の記事のおかげで、案外あっさりと解決できた。要は、Heroku環境のBundlerとローカル環境のBundlerとのバージョンが合ってなかったのである。出力メッセージの上の方に、

terminal.app
remote: -----> Ruby app detected
remote: -----> Installing bundler 2.2.16
remote: -----> Removing BUNDLED WITH version in the Gemfile.lock

と記載されていたから、どうやら自分のHeroku環境ではバージョン2.2.16のBundlerが使用されているようである。よって、ローカル環境のBundlerを改めてバージョン変更する。step.2と基本的な流れは同じ。

terminal.app
意味ないかもだけど、ホームディレクトリで再び作業。念のたm..
% cd ~

Bundlerの2.2.16をインストール
% gem install bundler:2.2.16

デプロイ対象アプリのあるディレクトリに戻る
% cd “アプリのディレクトリ”

同様にインストール
% gem install bundler:2.2.16

インストールされているバージョンの種類が増えているのを確認
% gem list bundler

Bundlerの2.2.17で生成されていたGemfile.lockを一旦削除
% rm gemfile.lock

Gemfile.lockをバージョン指定して再生成
% bundle _2.2.16_ install

再生成されたGemfile.lockに記載されているBUNDLED WITHと一致しているのを確認
% bundler -v

:warning: もしこの後も何らかの理由でGemfile.lockを削除するような事があった場合、その度に上のように特定のバージョンを指定してbundle installしなければ、毎回インストールされている最新バージョンのBundlerで再生成してしまう。若しくは、指定したいバージョンよりも新しい番号のBundlerをgem uninstall bundlerのコマンドでアンイストールしても良い。使わなければの話だが...

というか、step.2で「We suggest you to upgrade to the version that created the lockfile by running gem install bundler:2.2.16.(gem install bundler:2.2.16でバージョンアップする事をオススメするよ)」の警告メッセージが出た時に、素直にこれやっとけば良かった...orz

4.BundlerのプラットフォームをPCの環境に合わせる

Bundlerのバージョンを再度変更したので、ここで一旦コミットして三度目のデプロイを試みる。

terminal.app
remote:  !     Failed to install gems via Bundler.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed

なん...だと...!??!?三度目の正直はなかった。二度あることは三度あった...ってさっきと同じじゃん!?結局さっきのエラーは解決できていなかったようだ...(泣)どういうことだってばよ!?混乱しそうだったが、これもこちらの方の記事の続編で難なく解決できた!
解決への道筋は、上記のエラーメッセージの直前に記載されていた。

terminal.app
remote:        Your bundle only supports platforms ["x86_64-darwin-19"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.
remote:        Bundler Output: Your bundle only supports platforms ["x86_64-darwin-19"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.

1~3行目と4~6行目は同じことが書いてあるが、直訳すると「Bundlerのプラットフォームは["x86_64-darwin-19"]しかサポートしてないみたいだけど、あんたのローカル環境のプラットフォームは["x86_64-linux"]よ。bundle lock --add-platform x86_64-linuxでLOCKファイルに現在のプラットフォームを加えて、もっかい試してみな!」みたいになる。この「もっかい試して」とは「デプロイ」の事だろうが、問題の「x86_64-darwin-19」や「x86_64-linux」などは詳しくは知らないけどまぁザックリ言ってOSの事だろう。つまり、「Bundlerをバージョンアップさせたんだったら自身のローカルPCのOS環境に合わせなさい」と言っているのだ。そっかそっか。じゃあ合わせましょうか。

terminal.app
ここは素直にエラーメッセージで提案されているコマンドをコピペ実行
% bundle lock --add-platform x86_64-linux

差分を確認
% git diff

上の2つを実行すると、Gemfile.lockのPLATFORMSの欄に『x86_64-linux』が新たに追加されている事が分かる。

Gemfile.lock
PLATFORMS
  x86_64-darwin-19
+ x86_64-linux        ←これが追加される

:warning: デフォルトのプラットフォームが『x86_64-darwin-19』に設定されているようなので、これも再度Gemfile.lockを削除した後にbundle installしてしまえば、この『x86_64-linux』の行が消えてデプロイできなくなる。そのため毎回bundle lock --add-platform x86_64-linuxのコマンドを実行して、このプラットフォームを追加してあげなければならない。

因みに以前のBundler2.1.4だとこのPLATFORMSの箇所が『ruby』となっていたので、よく分からんけど、多分OSの環境に依存しない形でGemを管理していたんじゃないのかな(適当)
あとこれやっとけばstep.3の手順は省略できたかもしれないけれど、ローカルとリモートとのバージョン値は合わせておいた方が無難だろう。


さて、ここまで色々変更してきたんだから、もうさすがにデプロイできるだろうなぁ〜✨(大きな期待)
もっかい試してみるか・・・

terminal.app
remote:  !     Precompiling assets failed.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed

ギエピィィィィィィィィィィィィィィィィィィィ!!
ほわぁい!?ヘロクデベロップメントぴーぽー!!(泣)

この闘いが終わるのは、もう少し先のことであった...(後半へ続く)

参考記事

次回予告

Herokuデプロイ奮闘記(後編)


  1. ブログ執筆時のバージョン 

  2. デプロイ前初期バージョン 

  3. Matz' Ruby Implementationの略。C言語ベースのRuby。まつもとゆきひろ氏によって開発されたもので、最も一般的な処理系らしい。 

  4. bundle updateGemfile.lockを直接再生成する方法でも良いのだろうが、余計な問題が発生する恐れを避けるため主流?な方で実践。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
1
Help us understand the problem. What are the problem?