-
Notifications
You must be signed in to change notification settings - Fork 9
Clojure
このチュートリアルはHerokuにデプロイされるClojureとRingウェブライブラリについて扱って行きます。Herokuを使ったアプリケーションの開発や設計の仕方に関する一般的な情報は、Architecting Applications for Herokuを確認してください。
- インストールされたバージョンのLeiningenとJVMを含んだ、基本的なClojureの知識。
- あなたのアプリケーションはLeiningenを使用する必要があります。この記事はLeiningen 2.xの使用を前提にしていますが、1.xも同様に利用可能です。
- あなたのアプリケーションはOpenJDK のversion 6、もしくは 7で走る必要があります。
- Herokuのユーザアカウント。こちらで無料で簡単に取得ができます。
始めに、Heroku Toolbeltをローカルにインストール します。これはあなたのHeroku command-line client、Foreman、そしてGitのバージョン管理システムへアクセスを確かなものにします。
一度インストールできると、heroku
コマンドがシェルから使えるようになります。アカウントを作ったときに使ったE-mailアドレスやパスワードを使ってログインしてみます :
:::term
$ heroku login
Enter your Heroku credentials.
Email: [email protected]
Password (typing will be hidden):
Could not find an existing public key.
Would you like to generate one? [Yn]
Generating new SSH public key.
Uploading ssh public key /Users/adam/.ssh/id_rsa.pub
エンターキーをおすとすぐに存在しているssh
キーか新しいものをアップロードしてくれます。後でコードをプッシュするときに使います。
既に存在しているアプリケーションから始める人もいるかもしれませんが、もしそうでなければ、あなたに使ってもらえる簡単な"hello, world"のソースコードを用意しています :
:::clojure
(ns hello.world
(:require [ring.adapter.jetty :as jetty]))
(defn app [req]
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello, world"})
(defn -main [port]
(jetty/run-jetty app {:port (Integer. port) :join? false}))
また、lein new heroku helloworld
を実行することで、Herokuの環境で便利ないくつかの更なる便利な機能を持ったスケルトンプロジェクトを生成することができます。
HerokuはアプリケーションがClojureの物であるということを、project.clj
ファイルによって認識します。ここに、上で作ったClojure/Ringアプリケーションのためのporoject.clj
の例があります :
:::clojure
(defproject helloworld "0.0.1"
:dependencies [[org.clojure/clojure "1.5.1"]
[ring/ring-jetty-adapter "1.1.6"]]
:uberjar-name "helloworld-standalone.jar"
:min-lein-version "2.0.0")
ビルド用の生成物がバージョン管理に含まれてしまうのを防ぐために、以下のファイルを作成します :
:::term
/target
/pom.xml
/.lein-*
/.env
パブリックなリポジトリでは利用できない依存ファイルに依存しているプロジェクトは、プライベートなリポジトリにデプロイするのがいいでしょう。これをするための最も簡単な方法としてs3-wagon-privateLeiningenプラグインを使って、プライベートなS3のバケットを利用することです。
アプリケーションのルートディレクトリにあるテキストファイルであるProcfileを使って、Web Dynoを開始させるために何のコマンドを実行するべきかを明示的に宣言します。今回は、単体のClojure名前空間で実行する必要があります。
これは私たちのアプリケーションのためのProcfile
です :
:::term
web: java $JVM_OPTS -cp target/helloworld-standalone.jar clojure.main -m hello.world $PORT
これは、1個のweb
プロセスタイプと実行する必要のあるコマンドを宣言しています。"web"と付けることはここではとても重要です。これは、このプロセスタイプがHerokuのHTTPルーティングのスタックに積まれ、デプロイされた際にWebトラフィックを受け付けることを意味しています。
簡単な確認のために、ローカルではlein run -m hello.world 5000
を使ってアプリケーションを実行することができます。もしくはインタラクティブな開発のために、replからサーバを起動することができます。
:::term
$ lein repl
[...]
user=> (require 'hello.world)
nil
user=> (hello.world/-main 5000)
2013-07-01 13:52:49.575:INFO:oejs.Server:jetty-7.6.1.v20120215
2013-07-01 13:52:49.627:INFO:oejs.AbstractConnector:Started [email protected]:5000
#<Server org.eclipse.jetty.server.Server@2f26f304>
アプリケーションが5000番ポートで立ち上がります。curl
やブラウザで適切に動いているかを確認した上で、Ctrl-Cで終了します。
今、私たちはアプリの中に3つの主要な構成要素を持っています。project.clj
の中の依存関係ファイル、Procfile
の中のプロセスタイプ、そしてsrc/hello/world.clj
の中にある私たちのアプリのソースです。Gitに追加していきましょう :
:::term
$ git init
$ git add .
$ git commit -m init
(Herokuの)アプリケーションを作成します :
:::term
$ heroku apps:create
Creating glowing-snow-27... done
Created http://glowing-snow-27.herokuapp.com/ | [email protected]:glowing-snow-27.git
Git remote heroku added
コードをデプロイします :
:::term
$ git push heroku master
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (7/7), 710 bytes, done.
Total 7 (delta 0), reused 0 (delta 0)
-----> Heroku receiving push
-----> Clojure (Leiningen 2) app detected
-----> Installing OpenJDK 1.6...done
-----> Installing Leiningen
Downloading: leiningen-2.2.0-standalone.jar
Writing: lein script
-----> Building with Leiningen
Running: lein uberjar
Retrieving org/clojure/clojure/1.5.1/clojure-1.5.1.pom from
from http://s3pository.herokuapp.com/clojure/
[...]
Created /tmp/build_1y7nbplmlxu87/target/helloworld.jar
-----> Discovering process types
Procfile declares types -> web
-----> Compiled slug size: 51.4MB
-----> Launching... done, v1
http://glowing-snow-27.herokuapp.com deployed to Heroku
To [email protected]:glowing-snow-27.git
* [new branch] master -> master
Herokuにコードをデプロイしました、そしてProcfile
の中にプロセスタイプを指定しました。今、あなたはHerokuに対してプロセスタイプを実行するための指示を出す事が出来ます。Herokuはdynoに関連づいたコマンドを実行することでこれを行います。dynoとはHerokuにおける基本的な構成要素の単位になっている軽量コンテナのことです。
web
プロセスタイプが実行されているdynoがあることを確かめてみましょう :
:::term
$ heroku ps:scale web=1
アプリケーションのdynoの状態を確認することができます。このheroku ps
コマンドはあなたのアプリケーションの実行中のdynoをリストします :
:::term
$ heroku ps
=== web: `java $JVM_OPTS -cp target/helloworld-standalone.jar clojure.main -m hello.world $PORT`
web.1: up for 5s
ここにdynoが一つ走っています。
heroku open
を使ってブラウザでアプリを確認することができます。
:::term
$ heroku open
Opening glowing-snow-27... done
実行中のWeb dynoを一つだけ持っている事は、dynoが非アクティブになったあと1時間経つとスリープすることを意味します。これは再度立ち上がるときの最初のリクエストに対して数秒の遅れが発生することを意味します。後続のリクエストは通常通りに帰ってくるでしょう。
これを避けるために、web dynoを1個以上に増やすことが出来ます。例えば :
:::term
$ heroku ps:scale web=2
それぞれのアプリケーションごとに、Herokuは750時間のdyno無料利用時間を提供しています。2個のdynoで動いているアプリケーションは、月々のこの無料利用時間を超える可能性が高いので、増やしたものを戻してみましょう :
:::term
$ heroku ps:scale web=1
Herokuは、アプリケーションの内容物を実行しているすべてのdynoの出力ストリームから時系列イベントのストリームとしてログを扱います。HerokuのLogplexはこれらのイベントの全てをあつかう単体のチャネルを提供しています。
ログ用コマンドの一つを使って、実行中のあなたのアプリケーションの情報を見てみましょう。heroku logs
を実行します。 :
:::term
$ heroku logs
2011-03-16T03:28:32-07:00 heroku[web.1]: Running process with command: `java $JVM_OPTS -cp target/helloworld-standalone.jar clojure.main -m hello.world $PORT
2011-03-16T03:28:37-07:00 app[web.1]: 2011-03-16 10:28:37.181:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2011-03-16T03:28:37-07:00 app[web.1]: 2011-03-16 10:28:37.182:INFO::jetty-6.1.26
2011-03-16T03:28:40-07:00 app[web.1]: 2011-03-16 10:28:40.223:INFO::Started [email protected]:20184
2011-03-16T03:28:40-07:00 heroku[web.1]: State changed from starting to up
Herokuでは、必要な時にスクリプトとそのためだけに実行されるアプリケーションであるone-off dynoの中で、heroku run
を使って、コマンドを実行することが可能です。 あなたのアプリケーションの環境の中で実験のために、ローカルのターミナルでREPLプロセスを実行するためにこれを使います。
:::term
$ heroku run lein repl
Running lein repl attached to terminal... up, run.1
Downloading Leiningen to .lein/leiningen-2.2.0-standalone.jar now...
[...]
Clojure 1.5.1
user=>
Leiningenは大きさの面からあなたのSlugに含まれないため、ここでは必要に応じてダウンロードされます。replはあなたのアプリケーションの名前空間を利用可能にします。例えば :
:::term
user=> (require 'hello.world)
nil
user=> (hello.world/app {})
{:status 200, :headers {"Content-Type" "text/plain"}, :body "Hello, world"}
HerokuでのREPLの使用に関する更なる詳細についてはClojureアプリケーションのライブデバッギングの記事を確認してください。
あなたは簡単な(一回限りの = one-off)Clojureスクリプトを、あなたがデプロイしたアプリケーションの中にそのスクリプトが存在している限り、上記と同じようにターミナルから実行することができます。コンソールに出力をして終了するような、簡単なスクリプトを作ってみましょう :
:::clojure
(ns hello.hi)
(defn -main [& args]
(println "Hello there"))
この新しいコードをコミットしてデプロイします :
:::term
$ git add src/hello/hi.clj
$ git commit -m hi
$ git push heroku master
one-off dynoの中で、heroku run
を使ってこのスクリプトを実行します :
:::term
$ heroku run lein run -m hello.hi
Running lein run -m hello.hi attached to terminal... up, run.2
Hello there
デフォルトでは、Clojureアプリケーションはデータベースを備えていません。これは、あなたがきっとRedisやCouchDBのようなNoSQLデータベースを使いたがるか、(上の私たちのサンプルアプリの場合のように)全くデータベースを使う必要がないと考えているからです。
もし、SQLデータベースがあなたのアプリケーションに必要になったら、明示的に要求をします :
:::term
$ heroku addons:add heroku-postgresql:dev
- Clojureアプリケーションの開発とデプロイについて更に学ぶためにClojure categoryへ訪問する。
- データベースを利用したClojureウェブアプリケーションの構築を読んで、アプリケーションを拡張する。
- HerokuのClojureのサポートの技術的な側面を読む。
- DrawbridgeでリモートのClojureアプリケーションのライブデバッギングで扱われるデバッグについて学ぶ。
- アプリケーションを書いたり、構成したり、デプロイしたり、実行する時に直面するだろう概念について、技術的な大枠を知りたい場合にHerokuの仕組みを読む。