Heroku使い方メモ（Java）

Heroku を使って Java の Web アプリを作ってみる。

#基本的な話
##Heroku とは
PaaS の１つ。
Web アプリケーションを動かすための土台（プラットフォーム）を提供してくれるクラウドサービス。

Google でいうと Google App Engine、 Amazon でいうと AWS Elastic Beanstalk とかが同じようなサービスに当たる。

最初は Ruby (Ruby on Rails)をサポートした PaaS だったけど、現在は様々な言語によるプラットフォームをサポートしている。
Java もサポートされている。

データベースは、 PostgreSQL や MySQL などを使える。
ただし、無償利用の場合はデータ量などに制限がある。

##全体像
![heroku.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/eafc9be1-472a-79f0-d567-7fa2fa32c173.jpeg)

- アプリケーションのソースコードは Git を使って管理する。
- Heroku 上の Git リポジトリに Push すると、アプリケーションをビルドし、必要なファイルをかき集めて Slug と呼ばれるパッケージが作成される。
- Slug は Dyno と呼ばれる仮想の Unix コンテナにデプロイされ実行される。
- 実行された Web アプリには、インターネット越しにブラウザなどからアクセスできるようになる。

##アプリケーション
Heroku 上でプログラムを動かすために必要なソースコードや設定ファイルなど一式のこと。

- ソースコード
- 依存ファイル（pom.xml, build.gradle, Gemfile などなど）
- Procfile（Heroku 上で実行するコマンドを定義したファイル。詳細後述）

Heroku では、これらをまとめたものを「アプリケーション」と定義している。

##Slug
アプリケーションを Heroku 上で実行するために、ビルド、パッケージングして圧縮したもの。

- ソースコードをビルドしてできた実行ファイル。
- 依存するライブラリ一式。
- 言語の実行環境。

これらをまとめたものを、 Slug と呼ぶ。

##Buildpacks
Slug を構築する方法を定義したスクリプト。

Heroku は標準で Ruby, Node.js, Clojure, Java など様々な Buidlpacks を用意している。
これらは全てオープンソースで、 GitHub 上で開発されている（[Buildpacks | Heroku Dev Center](https://devcenter.heroku.com/articles/buildpacks#default-buildpacks)）。

標準でサポートされていない言語やフレームワークでも、 Buildpacks を作成すれば Heroku 上で動かすことができる。

##Dyno
アプリケーションを実行するための実行環境。
仮想の Unix コンテナのようなもの。

Heroku のサービスでは、この Dyno を単位にして性能などが説明されている。
たとえば、 Dyno １つだとメモリは 512 MBだとか、１つの Dyno が処理できるスレッドは 256 個まで、などなど。

デフォルトでは、１アプリケーションにつき１つの Dyno が割り当てられる。
複数の Dyno を割り当てることで性能を向上させることができるが、有償になる。

##無償利用する場合の制限
[こちら](https://devcenter.heroku.com/articles/limits) に様々な制限事項が記載されている。

主要そうなのをいくつかピックアップする。

###Dyno の制限
####メモリ
1Dyno のメモリは 512MB。

####稼働時間
1アプリケーションあたり、1Dyno 月 750 時間までは無料で稼働させられる。

1ヶ月 = 31日とした場合、月合計は 744 時間なので、普通に使う限りでは無料で使用することができる。

しかし、１つのアプリケーションに 2 つ以上の Dyno を割り当てたり、バッチ処理などのプロセスを別途稼働させた場合、それらの時間も合計されることになり、 750 時間の制限をオーバーすることになる（有償になる）。

###Slug のサイズ制限
300MB が上限。

Heroku に `git push` すると、リポジトリの内容がパッケージング・圧縮され、 Slug と呼ばれるファイルが作成される。
このサイズの上限が 300MB。

[Slug について](https://github.com/herokaijp/devcenter/wiki/slug-compiler)

※翻訳が古いためか、最大サイズが 200MB となっているが、 2014/11/22 現在は 300MB が上限の模様。

> Your slug size is displayed at the end of a successful compile. The maximum slug size is 300MB; most apps should be far below this limit.

###データベースの制限
PostgreSQL を無償で利用する場合は `Hobby Tier` というプランになり、以下のような制限がある。

- 登録できるデータは、全部で 10,000 行。
- 同時に開けるコネクションの数は、 20 まで。

[詳細](https://devcenter.heroku.com/articles/heroku-postgres-plans)


#Hello World
[Java の Getting Started](https://devcenter.heroku.com/articles/getting-started-with-java#set-up) を見ながら、 Java で Web アプリを動かすところまでやってみる。

##開発マシンの環境
###OS
Windows7 64bit SP1

###Git
[Git for Windows](http://msysgit.github.io/) 1.9.4

###SSH
Cygwin でインストール。
`%CYGWIN_HOME%\bin` にパスを通して、 `ssh` や `ssh-keygen` が使える状態にしておく。

####Git から使用する SSH を指定する
環境変数 `GIT_SSH` に Cygwin と一緒にインストールした ssh.exe のパスを設定しておく。

###Maven
[Maven](http://maven.apache.org/download.cgi) 3.2.3

※Maven3 が必要みたいです。

##Heroku のアカウントを作成する
[公式サイト](https://www.heroku.com/) から `Sign Up` して、アカウントを作成する。
必要なのはメールアドレスだけで、無償で作成可能。

##Heroku の CLI ツールをインストールする
[こちら](https://devcenter.heroku.com/articles/getting-started-with-java#set-up) の `Download Heroku Toolbelt for Windows` をクリックしてインストーラをダウンロード。

フルインストールすると Git と SSH もインストールされるみたいだが、自分の環境にはすでに Git と SSH はインストールしているので、 `Custom Installation` を選択して `Heroku Client` と `Foreman` だけをインスト―ルした。

インストールが完了したら、コマンドラインを開いて以下コマンドを実行。

```text:
> heroku version
heroku/toolbelt/3.12.1 (i386-mingw32) ruby/1.9.3
```

##Heroku Toolbelt で Heroku にログインする
```text:
> heroku login
Enter your Heroku credentials.
Email: <Heroku アカウントのメールアドレス>
Password (typing will be hidden):<パスワード>
```

メールアドレスとパスワードを聞かれるので、先ほど作成したアカウントの情報を入力する。

続いて SSH の鍵を作成するか尋ねられる。
Windows 環境だと、当然 `~/.ssh/id_rsa.pub` なんてパスは無効なので、 `Y` を選択してもエラーになって終了する。

なので、別途 `ssh-keygen` で鍵を作る。

##SSH の鍵を作成して登録する
任意のフォルダで以下のコマンドを実行。

```text:鍵の生成
> ssh-keygen.exe -t rsa
```

質問は全て「未入力 Enter」でOK。
`<Cygwin インストールフォルダ>/home/<ユーザー名>/.ssh` の下に、秘密鍵（`id_rsa`）と公開鍵（`id_rsa.pub`）が生成される。

```text:鍵を登録する
> heroku keys:add <先ほど作成した id_rsa.pub のパス>
Uploading SSH public key id_rsa.pub... done
```

これで鍵が登録される。
登録されているかどうかは `heroku keys` コマンドで確認できる。

##アプリケーションを作成する
```text:
> heroku create
Creating shielded-retreat-8659... done, stack is cedar-14
https://shielded-retreat-8659.herokuapp.com/ | git@heroku.com:shielded-retreat-8659.git
```

上記コマンドでアプリケーションが新規に作成される。
作成が完了すると、アプリケーションの URL と Git リポジトリの URL が表示される。

試しにアプリケーションの URL にアクセスしてみる。

![heroku.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/7de40a5c-afb9-bd99-9893-d2e1350b5c3e.jpeg)

###アプリケーション作成時に名前を指定する
```text:
> heroku create <アプリケーション名>
```

- `create` 時に任意の名前を指定することができる。
- 未指定の場合はランダムな文字列が使用される。

###アプリケーションの名前を変更する
```text:
> heroku apps:rename <変更後の名前> --app <変更前の名前>
```

変更が完了すると、変更後の Web アプリと Git リポジトリの URL が出力される。
なお、変更後の名前が既に使われている場合は、 `Name is already taken` というエラーメッセージが表示される。

##サンプルプロジェクトを取得する
Java のサンプルプロジェクトが Git リポジトリとして公開されているので、それをクローンしてくる。

```text:
> git clone https://github.com/heroku/java-getting-started.git
```

##プロジェクトを Heroku にアップする
先ほどクローンしてきた Git リポジトリのルートに移動して、リモートリポジトリを追加する。

```text:リモートリポジトリの追加
> cd java-getting-started

> git remote add heroku <git リポジトリのパス>
```

`heroku` という名前でアプリの Git リポジトリを登録したので、次はこのリポジトリに push する。

```text:push
> git push heroku master
```

なにやら Maven の出力が大量に出力されたのち、 `BUILD SUCCESS` と出て終了する。

さっそくブラウザから Web アプリにアクセスしてみる。
URL を直接ブラウザで指定してもいいけど、以下のコマンドを打つことで Web ブラウザを起動することもできる。

```text:
> heroku open
```

![heroku.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/e32d741d-1559-3745-1514-f4bfd43b2184.jpeg)

パスに `/db` を追加すると、データベース（PostgreSQL）を使用したサンプルページが表示される。

![heroku.JPG](https://qiita-image-store.s3.amazonaws.com/0/28302/14783157-6414-7594-6965-437ac41b77c0.jpeg)

アクセスするたびに時刻が記録され、結果が画面に表示される。

##各ファイルの意味とか
サンプルプロジェクトは、以下のようなファイル構成になっている。

```text:
│  README.md
│  LICENSE
│  .gitignore
│  Procfile
│  system.properties
│  pom.xml
└─src
    └─main
        └─java
                Main.java
```

|ファイルの種類|ファイル名|説明|
|:--|:--|:--|
|Heroku 関係       |Procfile               |foreman の設定ファイル。|
|                  |system.properties      |Heroku で動かす時の環境設定などを記載したファイル。|
|Java プログラム関係|src/main/java/Main.java|ソースコード。組み込みの Jetty を起動させている。|
|                  |pom.xml                |依存関係を定義した普通の pom.xml。|
|GitHub 関係       |.gitignore| |
|                  |LICENSE|    |
|                  |README.md|  |

###Procfile
foreman という Ruby のプログラム用の設定ファイル。
Heroku 上で実行するコマンドをここに記載する。

```text:Procfile
web:    java -cp target/classes:target/dependency/* Main
```

Procfile は `<プロセスタイプ>: <実行するコマンド>` という書式で記述する。
コマンドは複数記述することができ、その場合 foreman は各コマンドを別プロセスで起動する。

サンプルアプリでは、 `web` というコマンドが定義され、 Maven のビルド結果を使用して java のコマンドを実行している。
Heroku では、このように `web` という名前で定義されたコマンドが存在するとアプリケーションサーバーが起動するようになっている。

###system.properties
```text:system.properties
java.runtime.version=1.7
```

内容を見れば何となく想像できるが、 Java の実行環境のバージョンを指定している。

Heroku は、デフォルトでは Java 1.6 （1.6.0_27）が使用される。
このサンプルでは、 Java 1.7 （1.7.0_55）を使用するように指定している。

ちなみに、 Java 8 （1.8.0_20）もサポートされている。

※マイナーバージョンは 2014/11/13 現在[ドキュメントに記載されている](https://devcenter.heroku.com/articles/java-support#supported-java-versions) もの。

#サンプルをローカルで動かす
##データベースを用意する
###PostgreSQL をインストールする。
とりあえずローカルに PostgreSQL をインストールする。
手順は割愛（インストーラ落として叩くだけ）。

###データベース・ユーザーの作成
test という名前でデータベースを作成し、 test という名前のユーザーで書き込みできるようにしておく。
pgAdmin で GUI で簡単に作れるので方法は割愛。

###環境変数 DATABASE_URL の設定
環境変数 `DATABASE_URL` に以下のようにデータベースの情報を設定する。

```text:
> set DATABASE_URL=postgres://test:test@localhost:5432/test
```

何故この環境変数を設定するのかというと、サンプルアプリの実装を見ると分かる。

```java:Main.java
  private Connection getConnection() throws URISyntaxException, SQLException {
    URI dbUri = new URI(System.getenv("DATABASE_URL"));

    String username = dbUri.getUserInfo().split(":")[0];
    String password = dbUri.getUserInfo().split(":")[1];
    String dbUrl = "jdbc:postgresql://" + dbUri.getHost() + dbUri.getPath();

    return DriverManager.getConnection(dbUrl, username, password);
  }
```

`System.getenv("DATABASE_URL")` でデータベースの接続情報を取得してコネクションを生成している。
Heroku 上で動かすと、 Heroku 上の PostgreSQL の URL 情報をこの `DATABASE_URL` 環境変数から取得できる。

URL のフォーマットは `postgres://<username>:<password>@<hostname>:<port>/<path>` なので、それに合わせてローカルの設定をしている。

##Procfile を修正する
あたりまえだけど、 Procfile は Heroku(Linux) 上で動かすことが前提の記述になっており、 Windows 上で動かそうとするとエラーになる。

```diff:Procfile
- web:    java -cp target/classes:target/dependency/* Main
+ web:    java -cp target\classes;target\dependency\* Main
```

スラッシュをバックスラッシュに、コロンをセミコロンに変更する。

##ビルドする
```text:
> mvn install
```

##起動する
```text:
> foreman start web
```

##確認する
Web ブラウザを開いて `http://localhost:5000/` にアクセスする。


#ログの出力を確認する
ローカルで以下のコマンドを打つことで、 Heroku 上の Web アプリが出力しているログを確認することができる。

```text:
> heroku logs
```

また、 `--tail` オプションを追加することで監視も可能。

```text:
> heroku logs --tail
```

#SSH で接続する
Heroku 上のアプリケーションが動いているサーバーに SSH で接続できる。

```bash:
> heroku run bash
...

~ $ pwd
pwd
/app

~ $ ls
ls
Procfile  build  build.gradle  gradle  gradlew  gradlew.bat  src
```

#Gradle を使用する
Heroku では、 Gradle も使えるらしい。

前述の Maven でのサンプルを Gradle に切り替えて Heroku で動かしてみる。

##フォルダ構成
```text:
|-.gitignore
|-build.gradle
|-gradle/
|-gradlew
|-gradlew.bat
|-Procfile
|-system.properties
`-src/main/java
  `-Main.java
```

##変更点
###build.gradle
```groovy:build.gradle
apply plugin: 'application'

sourceCompatibility = '1.7'
targetCompatibility = '1.7'

mainClassName = 'Main'
applicationName = 'app'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.eclipse.jetty:jetty-servlet:7.6.0.v20120127'
    compile 'javax.servlet:servlet-api:2.5'
    compile 'postgresql:postgresql:9.0-801.jdbc4'
}

task stage(dependsOn: ['clean', 'installApp'])

task wrapper(type: Wrapper) {
    gradleVersion = '2.1'
}
```

- 依存関係は `pom.xml` にあったのをそのまま持ってきた。
- application プラグインを有効にして、ビルド後の起動ファイルの名前などを設定している。
- Gradle Wrapper を有効にしている。
- `stage` という名前のタスクを用意している。
    - `stage` というタスクは、 Heroku の git リポジトリに push したときに自動的に実行される特別なタスク。
    - このタスクで、プロジェクトをビルドし、コマンドラインから起動ができる状態にしておく必要がある。

###Procfile
```diff:Procfile
- web:    java -cp target/classes:target/dependency/* Main
+ web:    ./build/install/app/bin/app
```

- `installApp` タスクで生成される起動スクリプトを実行するように修正。

###.gitignore
```diff:.gitignore
- target
+ /build/
+ /.gradle/
```

- Maven ではなく、 Gradle 用に無視するファイルを修正。


##Heroku にデプロイする
以下コマンドを、プロジェクトのルートで実行する。

```text:
> git init

> heroku create

> heroku addons:add heroku-postgresql

> git push heroku master
```

フォルダを Git リポジトリ化した後、 Heroku に新規アプリケーションを作成、 PostgreSQL のアドオンを有効にし、 Heroku の Git にプッシュしている。

※`heroku` という名前の remote は、 `heroku create` した時に自動で登録されている。

「Gradle はまだベータ版です」みたいなメッセージが出るけど、一応ビルドは正常に完了する。

##動作確認
```text:
> heroku open
```

ブラウザが立ち上がり、 Maven の時と同じようにアプリが動作するのが確認できる。

#タイムゾーンを変更する
```text:
> heroku config:add TZ=Asia/Tokyo
```

#アドオンを使う
Heroku では、アドオンという形で追加機能を利用することができる。

アドオンには、条件によっては無料で使えるものもある。
ただし、無料であっても使用するにはクレジットカード番号の登録が必要になる。

##アドオンの追加方法
[こちら](https://addons.heroku.com/) にアドオンの一覧がある。

追加したいアドオンのページを開き、プランと対象のアプリケーションを選択して追加する。

追加されたアドオンは、ダッシュボードのアプリごとの画面で確認することができる。

##無料で使えるアドオンの例
###ロギング
アドオンなしの場合、 `heroku logs` でしかログを見ることができない。
この場合、参照できるログが最新 1500 行分までなど制約が大きい。

アドオンを入れることで、それより以前のログを参照したり、アーカイブ化したログをダウンロードしたりできるようになる。

- [Papertrail](https://addons.heroku.com/papertrail)
- [Logentries](https://addons.heroku.com/logentries)

###PostgreSQL のバックアップ
- [PG Backups](https://addons.heroku.com/pgbackups)

PostgreSQL のバックアップを１日１回取得することができる。

####コマンド
- 以下のコマンドは、アプリケーションを作成した（`heroku create` した）ディレクトリで実行する。
- そうでないディレクトリで実行する場合は、 `--app <アプリケーション名>` オプションを末尾につけて、対象のアプリを指定する必要がある。

#####バックアップを確認する
```text:
> heroku pgbackups
ID    Backup Time                Status                                Size   Database
----  -------------------------  ------------------------------------  -----  ------------
a001  2014/11/21 07:56.55 +0000  Finished @ 2014/11/21 07:56.56 +0000  2.0KB  DATABASE_URL
```

#####手動でバックアップを取得する
```text:
> heroku pgbackups:capture
```

※無料版の場合、手動バックアップは２個まで作成可能。

#####バックアップファイルをダウンロードする
```text:
> heroku pgbackups:url <ID>
"https://https://s3.amazonaws.com/hkpgbackups/app31504551@heroku.com/a001.dump?（後略）"
```

- `ID` には、ダウンロードしたいバックアップの ID を取得する。
    - バックアップの一覧表示をしたときに、一番左に表示される項目（`a001` など）。
- URL が出力されるので、ブラウザなどを使ってアクセスすると dump ファイルをダウンロードできる。

#####リストアする
```text:
> heroku pgbackups:restore DATABSE_URL <ID>
```

- 指定した ID のバックアップをリストアする。
- 試してないけど、 ID の代わりに URL を指定できるらしい。つまり、手動で取得したバックアップを何処かネットワーク上の見える場所に置いて、 URL を指定すれば任意のバックアップからリストアできる？

#####バックアップを削除する
```text:
> heroku pgbackups:destroy <ID>
```

- 指定した ID のバックアップを削除する。

###メール送信
[SendGrid](https://addons.heroku.com/sendgrid)

月２００通までなら無料で使用できるメール送信用アドオン。

####Java でメール送信を実装
```text:フォルダ構成
|-build.gradle
|-system.properties
|-Procfile
|-gradlew
|-gradlew.bat
|-gradle/
`-src/main/java/sample/heroku/mail/
   `-Main.java
```

```groovy:build.gradle
apply plugin: 'application'

sourceCompatibility = '1.7'
targetCompatibility = '1.7'

mainClassName = 'sample.heroku.mail.Main'
applicationName = 'mail'

repositories {
    mavenCentral()
}

dependencies {
    compile 'javax.activation:activation:1.1'
    compile 'javax.mail:mail:1.4'
    compile 'org.eclipse.jetty:jetty-servlet:7.6.0.v20120127'
    compile 'javax.servlet:servlet-api:2.5'
}

task stage(dependsOn: ['clean', 'installApp'])

task wrapper(type: Wrapper) {
    gradleVersion = '2.1'
}
```

```text:Procfile
web:    ./build/install/mail/bin/mail
```

```text:system.properties
java.runtime.version=1.7
```

```java:Main.java
package sample.heroku.mail;

import java.io.IOException;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class Main extends HttpServlet {
    private static final long serialVersionUID = 1L;

    private static final String SMTP_HOST_NAME = "smtp.sendgrid.net";
    private static final String SMTP_AUTH_USER = System.getenv("SENDGRID_USERNAME");
    private static final String SMTP_AUTH_PWD  = System.getenv("SENDGRID_PASSWORD");

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (req.getRequestURI().endsWith("/mail")) {
            try {
                sendMail(req,resp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            showHome(req,resp);
        }
    }

    private void sendMail(HttpServletRequest req, HttpServletResponse resp) throws Exception {
        Properties props = new Properties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.host", SMTP_HOST_NAME);
        props.put("mail.smtp.port", 587);
        props.put("mail.smtp.auth", "true");

        Authenticator auth = new SMTPAuthenticator();
        Session mailSession = Session.getDefaultInstance(props, auth);
        
        Transport transport = mailSession.getTransport();

        MimeMessage message = new MimeMessage(mailSession);

        Multipart multipart = new MimeMultipart("alternative");

        BodyPart part1 = new MimeBodyPart();
        part1.setText("This is multipart mail and u read part1......");

        BodyPart part2 = new MimeBodyPart();
        part2.setContent("<b>This is multipart mail and u read part2......</b>", "text/html");

        multipart.addBodyPart(part1);
        multipart.addBodyPart(part2);

        message.setContent(multipart);
        message.setFrom(new InternetAddress("me@myhost.com"));
        message.setSubject("This is the subject");
        message.addRecipient(Message.RecipientType.TO, new InternetAddress("to@myhost.com"));

        transport.connect();
        transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO));
        transport.close();
    }

    private class SMTPAuthenticator extends javax.mail.Authenticator {
        public PasswordAuthentication getPasswordAuthentication() {
            String username = SMTP_AUTH_USER;
            String password = SMTP_AUTH_PWD;
            return new PasswordAuthentication(username, password);
        }
    }
    
    private void showHome(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().print("Hello from Java!");
    }

    public static void main(String[] args) throws Exception{
        Server server = new Server(Integer.valueOf(System.getenv("PORT")));
        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.setContextPath("/");
        server.setHandler(context);
        context.addServlet(new ServletHolder(new Main()),"/*");
        server.start();
        server.join();
    }
}
```

メール送信の実装は [こちら](https://github.com/herokaijp/devcenter/wiki/sendgrid) を丸コピ。

Heroku にデプロイして、 `/mail` パスにアクセスすれば、メールが送信される。

#参考
- [特盛！Heroku | slideshare](http://www.slideshare.net/shunjikonishi/heroku-15670119)
- [foreman について - 君の瞳はまるでルビー - Ruby 関連まとめサイト](http://www.ownway.info/Ruby/index.php?foreman%2Fabout)
- [Gradleを使ったWebアプリケーションのさくさく開発（Herokuデプロイ編） - Splash of waters - 2nd. Season](http://jappy.hatenablog.com/entry/20130526/1369562871)
- [HerokuでDBのデータをバックアップする - アインシュタインの電話番号](blog.ruedap.com/2011/02/23/ruby-heroku-database-postgresql-backup)
- [herokaijp/devcenter Wiki](https://github.com/herokaijp/devcenter/wiki)
- [heroku に ssh ログイン - Qiita](http://qiita.com/kysnm/items/7a1fa5581fb80f61d1ee)