procfile

iwhurtafly edited this page Jul 14, 2012 · 7 revisions
Clone this wiki locally

Procfileは、Herokuのプラットフォーム上にあるアプリケーションのdynosにより実行されるコマンドが 何であるかを宣言するためのメカニズムです。それは、多種多様なHeroku dynoのラージスケールにおける process modelから生じています。 マルチタイプのworkerや、clockのような単体プロセス、 TwitterのストリーミングAPIの使用者、と言ったいかなるプロセスタイプを宣言するために Procfileを使うことが可能となります。

プロセスタイプのテンプレート

Procfileとは、アプリケーションにおけるプロセスタイプのリストのことです。 それぞれのプロセスタイプは、Procfileに記述されたプロセスが実行される時に呼び出されるコマンドの宣言となります。

Cedarスタック上では、全ての言語とフレームワークが、webプロセスタイプを宣言します。 このプロセスタイプは、アプリケーションサーバを起動させます。 Rails 3は、以下のプロセスタイプを管理しています。:

web: bundle exec rails server -p $PORT

Clojurewebプロセスタイプは、このような感じとなります。:

web: lein run -m demo.web $PORT
Herokuにより事前設定されているその他の環境変数は、コマンド内で参照することが出来ます。 最も有用なのは$PORT変数です。

Maven-generatedバッチファイルは、Tomcat Javaアプリケーションサーバーを実行します。:

web: sh target/bin/webapp

多くのアプリが、これらのデフォルト値で事足りるでしょう。より洗練されたアプリ、アプリが必要とするランタイムプロセスを より明確に宣言するのに推奨されるアプローチにこだわるのであれば、プロセスタイプを定義したいと思うかもしれません。 例えば、Railsアプリケーションは、このような追加のプロセスタイプで供給されます。

worker:  bundle exec rake jobs:work

プロセスタイプの宣言

プロセスタイプは、アプリのルートに置かれたProcfileというファイルを経由して宣言されます。 フォーマットは、1つのプロセスに対し1行となります。それぞれの行は、下記の形式である必要があります。:

<process type>: <command>

構文は次のように定義されます。:

  • <process type> -- プロセス名として、英数値文字が使えます。 web, worker, urgentworker, clock等です。
  • <command> -- 255文字以下の文字列が使えます。プロセスを起動するためのコマンドラインです。rake jobs:work等です。

`web`プロセスタイプは、HerokuのルーティングからHTTPトラフィックを受信する唯一のプロセスであるため、特別ですが、 その他のプロセスタイプは、任意で名称をつけることが可能です。

Foremanでのローカル開発

ローカルの開発環境で開発やデバックを行う際、リモートの環境と同じ状態で実行することは重要です。 このことは、互換性が無いことや、発見が難しいバグを本番環境へディプイする前に見つけ出すことを保証してくれます。 また、個々のコマンドが独立して機能する一連の流れに代わり、1つの集合体としてアプリケーションを扱います。

Foremanは、Procfileの後方で動作する アプリを動かすためのコマンドラインツールです。Heroku Toolbeltにより自動的にインストールされ、 Ruby Gemとしても利用可能です。

Procfileにwebworkerの両方を管理している場合、Foremanは、ターミナル上に割り込む形で、 そのプロセスの内1つを開始させます。

Foremanでアプリを動かしてみて下さい。:

:::term
$ foreman start
18:06:23 web.1     | started with pid 47219
18:06:23 worker.1  | started with pid 47220
18:06:25 worker.1  | (in /Users/adam/myapp)
18:06:27 web.1     | => Awesome web application server output
webプロセスは、5000番のポート上にロードします。なぜなら、Foremanが`$PORT`環境変数のデフォルト値として、この値を提供するからです。 この値は、ディプロイ時にHerokuのプラットフォームで使われるため、webプロセスが、このポート番号を受け入れることは重要なことです。

アプリをローカルでテストすることが出来ました。終了させるには、Ctrl-Cを押して下さい。

ローカル環境変数のセッティング

プロジェクトディレクトリの.envファイル内に保存される変数は、Foremanにより実行時、環境へ追加されます。 例えば、開発環境へRACK_ENVをセットすることが出来ます。

:::term
$ echo "RACK_ENV=development" >>.env
$ foreman run irb
> puts ENV["RACK_ENV"]
> development

.envファイルは、ソースコントロールへコミットしないで下さい。.envファイルは、ローカル設定にのみ使われるべきです。

Herokuへのディプロイ

Herokuによりサポートされているほとんどの言語で書かれたアプリをディプロイするのに、Procfileは必要はありません。 プラットフォームが使われている言語を自動的に検知し、アプリケーションサーバーを起動するために、デフォルトのwebプロセスタイプを クリエートしてくれます。

明確にProcfileをクリエートすることは、アプリケーションにおける、より上位のコントロールと柔軟性を保つために推奨されます。

Herokuが、Procfileを使えるようするために、Procfileをアプリケーションのルートへ追加し、Herokuへプッシュして下さい。:

:::term
$ git add .
$ git commit -m "Procfile"
$ git push heroku
...
-----> Procfile declares process types: web, worker
       Compiled slug size is 10.4MB
-----> Launching... done
       http://strong-stone-297.herokuapp.com deployed to Heroku

To git@heroku.com:strong-stone-297.git
 * [new branch]      master -> master

実行するプロセスの数を決定するために、heroku psを使用して下さい。表示されるリストは、左側のカラムが プロセスタイプを指し、右側のカラムがプロセスタイプに対応するコマンドを指しています。:

:::term
$ heroku ps
=== web: `bundle exec rails server -p $PORT`
web.1: up for 2m

全てのプロセスタイプから収集されたログメッセージのリストを参照するために、heroku logsを使用して下さい。

:::term
$ heroku logs
2011-04-26T01:24:20-07:00 heroku[slugc]: Slug compilation finished
2011-04-26T01:24:22+00:00 heroku[web.1]: Running process with command: `bundle exec rails server mongrel -p 46999`
2011-04-25T18:24:22-07:00 heroku[web.1]: State changed from created to starting
2011-04-25T18:24:29-07:00 heroku[web.1]: State changed from starting to up
2011-04-26T01:24:29+00:00 app[web.1]: => Booting Mongrel
2011-04-26T01:24:29+00:00 app[web.1]: => Rails 3.0.5 application starting in production on http://0.0.0.0:46999
2011-04-26T01:24:29+00:00 app[web.1]: => Call with -d to detach
2011-04-26T01:24:29+00:00 app[web.1]: => Ctrl-C to shutdown server

プロセスタイプのスケーリング

Herokuは、1つのwebプロセスを自動的に走らせますが、他のプロセスタイプはデフォルトでは開始されません。 workerを起動させるために、1dynoだけスケールする必要があります。:

:::term
$ heroku ps:scale worker=1
Scaling worker processes... done, now running 1

新たなプロセスタイプが走っていることを見るために、psをチェックして下さい。例えば、以下のようになります。:

:::term
$ heroku ps
=== web: `bundle exec rails server -p $PORT`
web.1: up for 2m

=== worker: `env QUEUE=* bundle exec rake resque:work`
worker.1: up for 5s

workerプロセスタイプからのメッセージを参照するために、heroku logs -ps workerを使用して下さい。:

:::term
$ heroku logs -ps worker
2011-04-25T18:33:25-07:00 heroku[worker.1]: State changed from created to starting
2011-04-26T01:33:26+00:00 heroku[worker.1]: Running process with command: `env QUEUE=* bundle exec rake resque:work`
2011-04-25T18:33:29-07:00 heroku[worker.1]: State changed from starting to up
2011-04-26T01:33:29+00:00 app[worker.1]: (in /app)

ここで参照するアウトプットは、Foremanからのアウトプットをローカルで参照するのと同じような結果となります。 Herokuのプロセスマネージャーからプロセスの状態に関するシステムメッセージが割り込まれます。

同様のコマンドで、スケールアップすることが可能です。例えば、2つのwebプロセスと4つのworkerプロセスをスケールしてみます。:

:::term
$ heroku ps:scale web=2 worker=4
Scaling web processes... done, now running 2
Scaling worker processes... done, now running 4

$ heroku ps
=== web: `bundle exec rails server -p $PORT`
web.1: up for 7m
web.2: up for 2s

=== worker: `env QUEUE=* bundle exec rake resque:work`
worker.1: up for 7m
worker.2: up for 3s
worker.3: up for 2s
worker.4: up for 3s

詳細はscalingを参照して下さい。

プロセスタイプのその他事例

プロセスを実行するProcfileモデルは、非常に柔軟です。希望するどんな任意のコマンドでも、 いかなるプロセス数であろうと、実行することが可能です。また、それぞれを独立させてスケールすることも可能です。

例えば、Rubyを使うことで、それぞれが異なるキューを消化する2種類のキューworkerを実行することが可能です。:

worker:        env QUEUE=* bundle exec rake resque:work
urgentworker:  env QUEUE=urgent bundle exec rake resque:work

その後、これらは独立してスケールすることが可能です。

:::term
$ heroku ps:scale worker=1 urgentworker=5

これ以外の読み物