趣味で作ったWebアプリをHerokuにデプロイしたのですが、4年前にまとめたHerokuにHaskellのアプリを公開するに比べてかなりデプロイが簡単になっていたので設定方法をまとめておこうと思います。
GW暇だったので簡単なバーチャルオフィスみたいなアプリを作りましたー!バックエンドはHaskellとServantで作ってます✌/
— lotz (@lotz84_) May 4, 2020
lotz84/remote-househttps://t.co/VWPRPtMN87 pic.twitter.com/CbkZ0IpMss
設定方法
結論、Dockerを利用したデプロイがとても楽です。
事前にHeroku側のアプリを新規作成しデプロイするWebサービスを用意しておきましょう。ここではweb-service
という名前のプロジェクトを作成したと仮定しますので以下のファイル名などは適宜置き換えて読んでください。
1. Dockerfile
を用意する
FROM haskell:8.8.3
WORKDIR /work
COPY stack.yaml web-service.cabal /work/
RUN stack build --only-dependencies
COPY . /work/
RUN stack build && stack install
CMD web-service-exe -p $PORT
Dockerfile
は様々な工夫の余地が考えられますが、ここでは手軽さを優先してHaskellの公式イメージを利用しています。Heroku上では効きませんがローカルでのビルド時にキャッシュを再利用できるように依存ライブラリのビルドだけ --only-dependencies
を使って分けています1。Herokuでは公開されるポートが $PORT
に設定されているので、この例では実行ファイルに渡しています。最初 CMD
で stack exec web-service-exe
のように stack exec
で実行するようにしていたのですが、これだと起動時に毎回GHCのダウンロードが走ってタイムアウトになってしまっていたので stack install
でバイナリをインストールしそれを実行する形式に変えました。
2. heroku.yml
を用意する
build:
docker:
web: Dockerfile
heroku.yml
には実行するコマンドを指定するrun
の項目も設定できますが、省略すれば Dockerfile
の CMD
が実行されます。
3: Heroku の stack を container
に設定する
$ heroku stack:set container
あとは普通に git push heroku master
すればHeroku上で公開されるはずです。
参考: Building Docker Images with heroku.yml | Heroku Dev Center
おまけ: Herokuボタンの設定
GitHubのREADME等にHerokuボタンを置いておくと誰でも自由に自分のHerokuにそのレポジトリのサービスをデプロイすることができます。Herokuボタンを設置するレポジトリにはapp.json
を置いておく必要があり、ここでstackを指定しておくのを忘れないようにしましょう。
{
"name": "Web Service",
"repository": "https://github.com/githubuser/web-service",
"stack": "container"
}
Herokuボタン自体は以下のMarkdownを記載すればOKです。
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
参考: Creating a 'Deploy to Heroku' Button | Heroku Dev Center