Yesod アプリケーションの本番環境デプロイ

デプロイ手順書

ソースをビルド (cabal build) して、生成された実行ファイルを Production 指定で動かすだけ。Yesod アプリケーションの ROOT ディレクトリ内で手順に沿ってコマンドを実行すればデプロイできる。Heroku 向けのデプロイ方法は、./deploy/Procfile に色々書いてある。

ビルド手順

cabal build するだけだが、依存モジュールを追加したり変更が色々あったりするので、以下のコマンドを順に実行する。個人的な運用方法としては、シェルスクリプトで && 結合して実行している。

cabal clean
cabal install --only-dependencies
cabal configure
cabal build

これで、./dist/build/${app_name}/${app_name} という実行ファイルが生成される。

Production 環境でアプリを実行

Production を引数に指定して実行するだけ。

./dist/build/${app_name}/${app_name} Production --port 8080

デフォルトのポート番号は4321 です。プロセスをデーモン化するには、Angel を利用できる。

アプリケーションプロセスのデーモン化

Angel を利用して、プロセス管理を行う。インストールは Cabal から出来る。

cabal install angel

Angel で管理するプロセスの設定ファイルを作成する

%{APP_NAME} は適宜設定すること。

config/angel.conf

workers {
  directory = "/var/www/%{APP_NAME}"
  exec      = "./dist/build/%{APP_NAME}/%{APP_NAME} Production --port 8080"
  pidfile   = "/var/run/yesod/%{APP_NAME}.pid"
  stdout    = "/var/log/yesod/%{APP_NAME}.stdout.log"
  stderr    = "/var/log/yesod/%{APP_NAME}.stderr.log"
}

Angel の実行

angel ./config/angel.conf

これで、設定ファイルの内容の exec のコマンドを実行してくれる。また、プロセスが落ちていたら再起動してくれる。

設定とか細かい事は本家のGitHub を参照してください。 https://github.com/MichaelXavier/Angel

Web サーバーとの連携

%{APP_ROOT} は適宜設定すること。

Nginx の設定

proxy_pass で起動した Yesod アプリケーションを指定するだけ。

upstream yesod_backend {
  server 127.0.0.1:8080;
}

server {
  listen 80;
  server_name yulii.net;

  root %{APP_ROOT}/static;

  proxy_connect_timeout 60;
  proxy_read_timeout    60;
  proxy_send_timeout    60;

  location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://yesod_backend;
  }

  location /static {
    expires 1y;
    root %{APP_ROOT};
  }
}

アプリケーションのROOT ディレクトリを Nginx の root に指定すると気持ち悪い(配下に設定ファイルとかある)ので、 /static を設定している。

番外編:アプリケーション実行ユーザの切り分け

実際の運用時には、アプリケーションの実行ユーザを Yesod 用に切り分けている。

Yesod 専用ユーザの作成

angel というユーザを作成する

useradd -d /var/opt/angel -s /sbin/nologin angel

Haskell や Cabal が使えるように /var/opt/angel/.bash_profile へパスを追加して、Angel をインストールする。

su - -s /bin/bash angel -c "cabal update"
su - -s /bin/bash angel -c "cabal install angel"

以上で、Yesod を動かす準備ができるので、su - -s /bin/bash angel でビルド&デプロイを実行する。

デプロイ用のシェルスクリプト

運用時に利用しているシェルスクリプトを作成しておく。各スクリプトで利用する $APP_ROOT は適宜設定する。

tasks/update-sources.sh

su - -s /bin/bash angel -c "cd $APP_ROOT && git pull"

tasks/build-production.sh

su - -s /bin/bash angel -c "cd $APP_ROOT && cabal clean && cabal install --only-dependencies && cabal configure && cabal build"

tasks/deploy-production.sh

Angel からWeb アプリケーションを起動するが、Angel 自体を nohup で起動する。

CONFIG_FILE="$APP_ROOT/config/angel.conf"
LOG_DIR="/var/log/yesod"
su - -s /bin/bash angel -c "nohup angel $CONFIG_FILE > $LOG_DIR/angel.stdout.log 2> $LOG_DIR/angel.stderr.log < /dev/null &"

リロードするときは、アプリケーションをビルドした後、Angel ではなくアプリケーションのプロセスを kill すると立ち上げ直してくれる。