プライベートユースでHeroku上で運用しているWebアプリ(Rails3.2 + ruby1.9.3)があるのですが
Cedar-14 stack end-of-life window begins 1 May 2019 | Heroku Dev Center
のアナウンスがあり、来年5月からビルドができなくなってしまうとのこと
ならば、アップグレードしておくかと
アップグレードガイド Upgrading to the Latest Stack | Heroku Dev Center に従って
$ heroku stack:set heroku-18 $ git commit --allow-empty -m "Upgrading to heroku-18" $ git push heroku master
とheroku-18 stackベースでデプロイしてみたところ、buildエラーに...。
remote: ! An error occurred while installing ruby-1.9.3-p551 remote: ! remote: ! Heroku recommends you use the latest supported Ruby version listed here: remote: ! https://devcenter.heroku.com/articles/ruby-support#supported-runtimes remote: ! remote: ! For more information on syntax for declaring a Ruby version see: remote: ! https://devcenter.heroku.com/articles/ruby-versions
なんと..
こりぁアカン..
どうやらruby-1.9.3は新しいstackでサポートされてないようです..
ということでcontainerでデプロイするように作戦変更しました。
(Rails/rubyの段階的アップグレードはとうの昔に放棄)
containerベースへの移行方法
Dockerfileを作ってローカル環境にてdocker上で動くようにできたら、
あとは
$ heroku container:login $ heroku container:push web # コンテナイメージのpush $ heroku container:release web # pushしたイメージのリリース
です。
既存のCedar-14 stackでのアプリケーションが稼働中であっても問題なく上書き?でデプロイできました。
コードの修正点は
config/database.yml
production: <<: *default url: <%= ENV['DATABASE_URL'] %>
それ以外としては、
.dockerignore
tmp/pids/server.pid
を追加しておくとよいと思います。
トラブルシューティング
やはりというかいくつか問題が発生したのでその対策です。 もっとスマートな方法はあるはず。。
トラブル1: Boot timeoutエラー
Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
どうやらアプリケーションがPORTにアクセスできてないようです
Qiitaの記事 DockerでRailsの環境構築してHerokuへデプロイする - Qiita では
CMD ["rails", "server", "-b", "0.0.0.0"]
でサーバー起動していますが同様にしたら上記のエラーになってしまいました
どうやら自分の環境ではWebrickを使っているからのようです。。 (Rails5だとデフォルトサーバーのpumaの設定ファイル内で環境変数PORTにアクセスしているから問題ない)
本来ならばpumaを使うようにするべきだと思いますが、とりあえず次のように修正して解決しました。
CMD bundle exec rails server -b 0.0.0.0 -p $PORT
ただ、
配列形式の
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0", "-p", "$PORT"]
にすると
2019-07-17T13:43:33.652404+00:00 heroku[web.1]: Starting process with command `bundle exec rails s -p \8224 -b 0.0.0.0
というエラーになりNGでした...
謎。。
トラブル2: assets precompileされていなくアプリケーションエラー
An ActionView::Template::Error occurred in page#index: application.css isn't precompiled
が出ます
assets precompileが必要です。(今まではHerokuデプロイ時に自動でやってくれていた)
Dockerfile に以下の行を追加して解決しました
RUN bundle exec rake assets:precompile
Rakefile を ADD/COPY する前だと
No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)
が出るので要注意です
トラブル3: コンパイルしたassetsにアクセスできない
ActionController::RoutingError (No route matches [GET] "/assets/application-bf61d1c6485bd814e710bb58a3622bea.css"):
コンパイルされたCSSにアクセスできず、レイアウトが崩れてしまいました
Rails 4+ Asset Pipeline on Heroku | Heroku Dev Center を参考に
Gemfile に
gem 'rails_12factor', group: :production
を追加して解決しました
トラブル4: development環境用にインストールしたgemが悪さをする
development環境用のgemがインストールされていてproduction環境で悪さをしているということがありました
production環境用のgemのみインストールするのは
# RUN bundle install # を RUN bundle install --without test development # に変更
でよいのですがこれだとローカルの開発環境でdockerビルドしたときに開発用のgemがインストールされません
ARGを使って使い分けるようにしました
Dockerfile
ARG bundle_install_opt="--without test development" RUN bundle install ${bundle_install_opt}
docker-compose.yml
version: '2' services: web: build: context: . args: - bundle_install_opt
というようにすると、ローカル環境では docker-compose build
とすれば開発用のgemがインストールされたイメージをビルドできます
とりあえず、引き続きメンテナンスできそうで一安心です