Node.js+expressをHerokuにデプロイ

Herokuの使い方も覚えようかと試してみたメモ。
全体の流れはこの辺を参考にさせていただきました。
Node.jsをHerokuへデプロイ - Qiita

あとNode.js+expressのサンプルアプリはこの辺を参考にしてます。
Express 4 をはじめよう - Qiita

  • Herokuのユーザ登録

Herokuのサイトでユーザ登録する。
https://www.heroku.com/

  • Heroku Toolbeltのインストール

Heroku Toolbeltというコマンドラインツールをダウンロードしてインストールする。
https://toolbelt.heroku.com/

Macの場合は「heroku-toolbelt.pkg」というパッケージフィルで配布されてるのでそれをダブルクリックしてインストーラ起動するのでデフォルトでOK。

  • Herokuにログイン

コマンドラインからheroku loginコマンドを実行してログインする。メールアドレスとパスワードを聞かれるので入力する。

$ heroku login
Enter your Heroku credentials.
Email:
Password (typing will be hidden):
Authentication successful.
  • ssh鍵の登録

ssh鍵を登録する。既存の鍵があればそれを登録なければssh-keygenとかで生成してから登録。

$ heroku keys:add ~/.ssh/id_rsa.pub
  • expressでローカルにWebアプリを作る

このへん参考にしてexpress-sampleという名前のアプリを作ってローカルで動く状態にする。
Express 4 をはじめよう - Qiita

$ mkdir express-sample
$ cd express-sample
$ git init
(アプリ作る)
$ git add .
$ git commit -m "initial commit"
$ git remote add origin git@github.com:minamijoyo/express-sample.git
$ git push -u origin master

コード管理のためとりあえずgithub側にもpushしておく。
注意点としてexpressのlistenポート番号はprocess.env.PORTを参照するようにしておかないとHerokuのデプロイがうまくいかない。(詳細は最後のデバッグ節参照)

今回作成したコードは以下に置いてます。
https://github.com/minamijoyo/express-sample

  • Heroku用のローカルの準備

package.jsonにengineを追記。

{
  "name": "express-sample",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app"
  },
  "engine": {
    "node": "v0.10.28",
    "npm": "1.4.10"
  },
  "dependencies": {
    "express": "*",
    "jade": "*"
  }
}

nodeとnpmのバージョンはそれぞれ以下で調べられる。

$ node -v
v0.10.28
$ npm -v
1.4.10

Procfileを作成する

web: node app.js

一旦コミットしておく

$ git add .
$ git commit -m "Add heroku setting"
$ git tag v0.0.1
  • Heroku側の準備

heroku create (アプリ名)でHeroku側にアプリを作る。https://(アプリ名).herokuapp.com/ がそのままURLになるので注意。

$ heroku create minamijoyo-express-sample
Creating minamijoyo-express-sample... done, stack is cedar-14
https://minamijoyo-express-sample.herokuapp.com/ | https://git.heroku.com/minamijoyo-express-sample.git
Git remote heroku added

この時点でhttps://(アプリ名).herokuapp.com/ にアクセスすると以下のような画面が見えていればとりあえず初期化はできてる。

Heroku | Welcome to your new app!
Refer to the documentation if you need help deploying.
  • Herokuにデプロイ

heroku createした際に自動でgit remote herokuが登録されているのでpushすれば公開される。

$ git push heroku master

heroku openで既定のブラウザでURL開いてくれる。

$ heroku open

以降は修正のたびにgit push heroku masterすれば自動で更新される。

ただ文字列出してるだけですがこんなかんじでちゃんと公開されてる。
https://minamijoyo-express-sample.herokuapp.com/

これで何かのデモとか作ったらシュッと公開できるかんじでよいのではないかと。

なんかエラー出てうまく表示されない場合はheroku logsでログを見ればエラーが発生した原因がわかるかも知れない。
知らなくてハマったのだけど、80番ポートを明示的にバインドしようとするとこんなかんじのエラーが出る。

$ heroku logs
(中略)
2014-12-11T07:20:39.750516+00:00 heroku[web.1]: Starting process with command `node app.js`
2014-12-11T07:20:41.313410+00:00 app[web.1]:
2014-12-11T07:20:41.315690+00:00 app[web.1]:     at listen (net.js:1064:10)
2014-12-11T07:20:41.315694+00:00 app[web.1]:     at EventEmitter.app.listen (/app/node_modules/express/lib/application.js:559:24)
2014-12-11T07:20:41.313481+00:00 app[web.1]: events.js:72
2014-12-11T07:20:41.315699+00:00 app[web.1]:     at Module.load (module.js:356:32)
2014-12-11T07:20:41.315697+00:00 app[web.1]:     at Object.Module._extensions..js (module.js:474:10)
2014-12-11T07:20:41.315700+00:00 app[web.1]:     at Function.Module._load (module.js:312:12)
2014-12-11T07:20:41.313863+00:00 app[web.1]:         throw er; // Unhandled 'error' event
2014-12-11T07:20:41.313870+00:00 app[web.1]:               ^
2014-12-11T07:20:41.315688+00:00 app[web.1]:     at errnoException (net.js:904:11)
2014
-12-11T07:20:41.315685+00:00 app[web.1]: Error: listen EACCES
2014-12-11T07:20:41.315689+00:00 app[web.1]:     at Server._listen2 (net.js:1023:19)
2014-12-11T07:20:41.315696+00:00 app[web.1]:     at Module._compile (module.js:456:26)
2014-12-11T07:20:41.315692+00:00 app[web.1]:     at Server.listen (net.js:1138:5)
2014-12-11T07:20:41.315695+00:00 app[web.1]:     at Object.<anonymous> (/app/app.js:13:5)

「Error: listen EACCES」あたりが怪しそうなのでググったところherokuでは明示的にlistenポート番号指定してはいけなくて、こんなかんじでprocess.env.PORTを参照するようにしないといけないらしい。

var express = require('express');
var app = express();
var port = process.env.PORT || 3000;

(中略)

app.listen(port);