Haskell
buildpack
dokku
Stackage
stack

Dokku環境を構築してHaskellのアプリケーションをデプロイする

この記事は Recruit Engineers Advent Calendar 2017 の7日目の記事です。

はじめに

普段はiOSエンジニアをしていますが、学習目的でちょっとしたWebサイトやツールなどをHaskellで作って遊んでいます。プロジェクト作成からデプロイまでを気軽に行いたいのでDokku環境を構築しています。今回はUbuntuにDokku環境を構築してHaskellのアプリケーションをデプロイする、入門的なお話をします。

開発環境

  • Hostマシン
    • Ubuntu 16.04
    • Dokku 0.10.5
  • Haskell

以下、HostとClientを切り替えながら作業するので、紛らわしくないようにタイトルに(Host)/(Client)のタグを付けました。

なぜDokkuなのか

PaaSを選定する上で Deis も検討したのですが、Dokkuのほうがマシンの推奨環境がより小さいためこちらを選択しました。それだけです。どちらもBuildpack/Dockerfile/DockerImageでのデプロイに対応しており使い勝手などは似ていそうです。現在は適当なVPSにDokkuをインストールして利用しています。

Dokkuをインストール (Host)

Dokkuのインストールは以下の2行です。とっても簡単ですね。

$ wget https://raw.githubusercontent.com/dokku/dokku/v0.10.5/bootstrap.sh
$ sudo DOKKU_TAG=v0.10.5 bash bootstrap.sh

Dokkuがインストールされていることを確認します。

$ dokku version
0.10.5

Dokkuの初期化 (Client)

DokkuがインストールされるとHostマシンで初期化用のWebページが立ち上がった状態になります。ブラウザでHostマシンのIPにアクセスすると以下のようなWebサイトが表示されます。

スクリーンショット 2017-12-04 23.56.07.png

各入力項目の説明をします。

  • SSH Public Key
    • git push/fetch などに使うSSH公開鍵です
    • GitHubにSSH公開鍵を登録するのと同じ感覚です
  • Hostname
    • ドメインを入力します
  • Use virtualhost naming for apps
    • チェックを入れるとアプリケーション名がサブドメインになります。 http://<app-name>.<yourdomain> でアプリケーションへアクセスすることができます。

Dokkuアプリケーションを作成 (Host)

dokku apps:create でアプリケーションを作成します。今回は haskell-dokku-sample というアプリケーションを作りました。

$ dokku apps:create haskell-dokku-sample
Creating haskell-dokku-sample... done

$ dokku apps:list
=====> My Apps
haskell-dokku-sample

Dokkuの操作に関しては dockland というgemを使えば、Client側から簡単に操作することも可能です。

Haskellのアプリケーションを作成 (Client)

初期化

stack new でプロジェクトを初期化します。

$ stack new haskell-dokku-sample simple
$ stack build
$ stack exec haskell-dokku-sample
hello world

アプリケーション

今回はシンプルなWebのアプリケーションとします。 build-dependswarp wai http-types を追加します。

haskell-dokku-sample.cabal
executable haskell-dokku-sample
  hs-source-dirs:      src
  main-is:             Main.hs
  default-language:    Haskell2010
  build-depends:       base >= 4.7 && < 5
                     , warp
                     , wai
                     , http-types

Webアプリケーションのコードは以下のとおりです。リクエストに対し Hello! を返すだけの単純なものです。

src/Main.hs
{-# LANGUAGE OverloadedStrings #-}
module Main where

import Network.Wai (responseLBS, Application)
import Network.HTTP.Types (status200)
import Network.Wai.Handler.Warp (run, Port)
import System.Environment (getEnvironment)
import Data.List (lookup)
import Data.Maybe

main :: IO ()
main = do
  port <- getPort
  run port helloApp

helloApp :: Application
helloApp req respond = respond $ responseLBS status200 [] "Hello!"

getPort :: IO Port
getPort = getEnvironment >>= return . port
  where
    port = fromMaybe defaultPort . fmap read . lookup "PORT"

defaultPort :: Port
defaultPort = 80

Dokkuにデプロイする前にビルドが通ることを確認します。

$ stack build

Buildpack

DokkuはHerokuのBuildpackに対応しています。HaskellのBuildpackはHerokuで公式にサポートされていないため以下を利用します。

mfine/heroku-buildpack-stack

.buildpacks ファイルを以下のように作成します。

.buildpacks
https://github.com/mfine/heroku-buildpack-stack

Procfile

DokkuはHerokuのように Procfile を認識してプロセスを実行します。上記Buildpackでは実行ファイルにパスが通った状態になるので Procfile を以下のように作成します。

Procfile
web: haskell-dokku-sample

Dokkuにデプロイする (Client)

DokkuはこれまたHerokuのように git push コマンド一発でデプロイできます。

$ git push dokku master
...
=====> Downloading Buildpack: https://github.com/mfine/heroku-buildpack-stack
=====> Detected Framework: Haskell
...
=====> Application deployed:
       http://haskell-dokku-sample.yourdomain.com

To yourdomain.com:haskell-dokku-sample
 * [new branch]      master -> master

これで http://haskell-dokku-sample.yourdomain.com に対してWebアプリケーションがデプロイされました。
お手持ちのブラウザから確認します。

スクリーンショット 2017-12-05 0.55.15.png

表示されましたね :tada: :tada: :tada:

最後に

今回はDokku環境の構築からHakellのアプリケーションのデプロイまでを紹介しました。気軽にデプロイできる環境を一つ用意しておくと非常に重宝します。趣味レベルのアプリケーションにHeroku使うのもな、、と考えている方におすすめです。次はSwiftアプリケーションのデプロイなんかも試してみたいと思います。