herokuにHaskellのウェブアプリをデプロイするのにbuildpack APIを調べようとしたらDockerをつかったリリースができることを知ったので、試した。
デプロイするアプリケーションはここでつくったものがあるのでこれを利用する。イメージの名前はeiel/wai-sample
です。
準備
dockerコマンドが使える状態になっている必要があります。
また、herokuコマンドをインストールして、dockerプラグインをインストールする必要があります。
$ heroku plugins:install heroku-docker
Procfileの作成
Procfileを作成します。/app/wai-sampleで実行できるようにしてありますので、
web: /app/wai-sample
とします。
app.json
app.jsonに image キーが必要になります。eiel/wai-sample
を利用します。
{
"image": "eiel/wai-sample"
}
heroku docker:init
ここまで進めるとheroku docker:init
で必要なファイルを生成できます。
$ heroku docker:init
このコマンドを実行するとDockerfileとdocker-compose.ymlが生成されます。
FROM eiel/wai-sample
web:
build: .
command: 'bash -c ''wai-sample'''
working_dir: /app/user
environment:
PORT: 8080
ports:
- '8080:8080'
shell:
build: .
command: bash
working_dir: /app/user
environment:
PORT: 8080
ports:
- '8080:8080'
volumes:
- '.:/app/user'
デプロイする
herokuにアプリケーション領域をつくってデプロイします。
$ git init
$ git add .
$ git commit -m "initial commit"
$ heroku create
$ heroku docker:release
これで終了です。
$ heroku open
で、ウェブアプリをブラウザでひらくことができます。
もっと詳しく
docker:releaseはDockerイメージ内の/app
をherokuにアップロードしてくれます。その後cd /app/user && 「Procfile」
の内容を実行してくれます。
これだけわかっていればHaskell以外のアプリケーションも動かせると思います。
docker release内部ではRelease APIを使用しているだけなので、dockerを使わずともLinux用のバイナリを生成してRelease APIをつかってデプロイすることもできると思います。
バイナリの生成
Docker内で生成しています。これを補助するために作成したDockerImageも用意しています。
Dockerfileはこっちにあります。
ビルド時間短縮するために warp のビルドまで済ませてあります。
このイメージをもとに wai-sample のイメージを生成しています。
/appにバイナリを配置して、/app/userディレクトリをつくっておくことでheroku docker:release
でそのまま使えるようにしています。
CIでビルド
Docker内で生成してもよいですが、CIでビルドしてバイナリだけとりだして、Docker化してあげる方法があります。
イメージも小さくなるのでおすすめです。(いっそCIでheroku releaseしたいけど今回はやりませんでした)
CircleCIだとコンパイル結果のキャッシュをきかせたりできるので2回目以降のビルドはとても早いです。
circle.ymlの例
machine:
services:
- docker
dependencies:
cache_directories:
- "~/.stack"
pre:
- wget -q -O- https://s3.amazonaws.com/download.fpcomplete.com/ubuntu/fpco.key | sudo apt-key add -
- echo 'deb http://download.fpcomplete.com/ubuntu/precise stable main'|sudo tee /etc/apt/sources.list.d/fpco.list
- sudo apt-get update && sudo apt-get install stack -y
override:
- stack setup
- stack install
- stack build --test --only-dependencies
test:
override:
- stack test
deployment:
docker:
branch: master
commands:
- mkdir dist
- cp `stack path --local-bin-path`/wai-sample dist/
- docker build -t eiel/scotty-sample -f Dockerfiles/CircleCI .
- docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
- docker push eiel/wai-sample
FROM google/debian:wheezy
COPY dist/scotty-sample /app/
RUN mkdir /app/user
google/debian:wheezyを指定しているのは、私がGCEで使うことが多いので、指定しているだけです。お好みで。