この記事は Recruit Engineers Advent Calendar 2017 の7日目の記事です。
はじめに
普段はiOSエンジニアをしていますが、学習目的でちょっとしたWebサイトやツールなどをHaskellで作って遊んでいます。プロジェクト作成からデプロイまでを気軽に行いたいのでDokku環境を構築しています。今回はUbuntuにDokku環境を構築して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サイトが表示されます。
各入力項目の説明をします。
- 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-depends
に warp
wai
http-types
を追加します。
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!
を返すだけの単純なものです。
{-# 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で公式にサポートされていないため以下を利用します。
.buildpacks
ファイルを以下のように作成します。
https://github.com/mfine/heroku-buildpack-stack
Procfile
DokkuはHerokuのように Procfile
を認識してプロセスを実行します。上記Buildpackでは実行ファイルにパスが通った状態になるので 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アプリケーションがデプロイされました。
お手持ちのブラウザから確認します。
表示されましたね
最後に
今回はDokku環境の構築からHakellのアプリケーションのデプロイまでを紹介しました。気軽にデプロイできる環境を一つ用意しておくと非常に重宝します。趣味レベルのアプリケーションにHeroku使うのもな、、と考えている方におすすめです。次はSwiftアプリケーションのデプロイなんかも試してみたいと思います。