soranoba
soranoba Author of soranoba.net
programming

heroku.ymlでRailsをデプロイする

Rails (API) + React.js (Web)を1つのレポジトリで作成し, RailsをHerokuに, React.jsをNetlifyにデプロイしたところ, Heroku周りで色々躓いたので備忘録がてら書こうと思います.

ディレクトリ構成

$ tree -L 2 .
.
├── README.md
├── api
│   ├── Gemfile
│   ├── Gemfile.lock
│   ├── Makefile
│   ├── README.md
│   ├── Rakefile
│   ├── app
│   ├── bin
│   ├── config
│   ├── config.ru
│   ├── db
│   ├── lib
│   ├── log
│   ├── public
│   ├── spec
│   ├── storage
│   ├── test
│   ├── tmp
│   └── vendor
└── web
    ├── Makefile
    ├── node_modules
    ├── package-lock.json
    ├── package.json
    ├── public
    ├── scripts
    ├── src
    ├── test
    └── webpack.config.js

19 directories, 15 files

apiにRailsを, webにReact.jsを置く形にしています.

ディレクトリを指定してHerokuにデプロイする

最初に躓いたのはここでした.
Getting Started on Heroku with Rails 5.xにあるように, Gemfileがトップレベルにある形を取っていれば, Github integrationのみで簡単にデプロイできそうですが, その為にレポジトリを分けるのも癪だったので試行錯誤することになりました.

デプロイするパス (Gemfileがあるディレクトリ) を指定することはできないので, Building Docker Images with heroku.ymlにある, コンテナを自分で作る方法を取ることにしました.

Github integrationはこの方法でも使えるので, デプロイ方法を変更するだけです.

Rails用のDockerfileを作成する

Targeting a stage from a multi-stage buildを参考に以下のようなDockerfileを作成します.

FROM heroku/heroku:18-build AS builder
RUN gem install bundler:1.16.4
WORKDIR /app
COPY api .
RUN bin/bundle install --jobs=4 --retry=3 --path=vendor/bundle --without="development:test"

FROM heroku/heroku:18 AS production
RUN gem install bundler:1.16.4
COPY --from=builder /app /app
WORKDIR /app
CMD [ "bundle", "exec", "puma" ]

この時, CMDを指定しないとunsupportedというエラーメッセージだけが残されてデプロイに失敗するので注意が必要です.
その他のHeroku独自の制約については, Dockerfile commands and runtimeに記載があります.

RUN bin/bundle install --jobs=4 --retry=3 --path=vendor/bundle --without="development:test"

の部分は, sqlite3 or pgのハンドリングをする為の指定を行なっています.
Specifying gems and groupsにあるようにconfigによるハンドリングを行なったところで設定が足りないのでこのコンテナではdevelopment用のビルドができないので, ここで指定しています.

手元でdocker buildが通ることを確認したら, 次はheroku.ymlの作成です.

heroku.ymlで起動コマンドを指定する

RAILS_ENVを環境変数で設定します.

heroku config:set RAILS_ENV=production

これでRelease Phase以降環境変数として利用できるので, 以下のように作成します.
(Build Phaseで参照したい場合は, Setting build-time environment variablesの方法を用いればできそうです)

build:
  docker:
    web: Dockerfile

release:
  command:
    - bundle exec rake db:migrate

run:
  web: bundle exec puma -t 5:5 -e ${RAILS_ENV:-production} -p ${PORT:-3000} -C config/puma.rb config.ru

ymlの構文エラーの場合に以下のようなエラーが出て, 時間を無為にするので注意が必要です. (無為にしました)

=== Fetching app code..
=!= Unknown error

ドキュメントが散らばっていたり, エラーメッセージが分かりにくかったり (というより情報がない) で内容の割に苦労したので, 誰かしらの役に立てば幸いです.

(Updated: )

comments powered by Disqus