話題のPaaS型サーバー、Herokuでアプリを公開しよう
Herokuに定番の『Hello, World』とだけ表示するアプリケーションを公開します。その後、そのサービスを前回使用した日時を表示する機能を追加します。これにはRedisというKeyValueStoreを利用します。
より実践的な内容は「ワーク」として用意しましたので、記事を読み終わったらワークを実施してください。
最近話題のPaaSクラウドサーバー、Herokuとは?
Herokuはワンコマンドでサービスをデプロイ(公開)できる、クラウド型のレンタルサーバーです。無料から利用できます。 Ruby, Node.js, Python, Javaのいずれかの言語で作られたサービスであれば1コマンドでサーバーを用意、公開開始できます。
ユーザが増えてきたら1コマンド、もしくはマウスでドラッグするだけでサーバを数秒で増やす事もできます。
デフォルトのデータベースはPostgreSQLが用意されていますが、ClearDBやAmazonRDSなどMySQL系サーバーもアドオンで提供されています。
データベース系のみでなく、NewRelic(スロウクエリーの監視やサーバダウンの検知)など、サーバーに必要なあらゆる機能がアドオンとしても提供されているのが特徴です。また、サーバーもアドオンも、基本無料で使えます。ユーザ(アクセス数)が増えたら有料のものが多いです。
[下準備] Sinatra Frameworkで「Hello World!」表示アプリ作成
既にRubyがインストール済みの方を想定していますので、もしまだの方は第1回の記事を見て下さい。 今回はHerokuを使ってみるのがメインですので、最も簡単なアプリの作成だけを行います。
Ruby言語のマイクロフレームワーク、Sinatraを利用して、アクセスすると「Hello World!」と表示するページ・アプリを作りましょう。 Sinatraの公式ホームページを参考にすればすぐできます。
「hello」などのフォルダ名でフォルダを作り、その中に移動($ cd hello
)し、下記ファイルを作成してください。
myapp.rb
1 2 3 4 5 | require 'sinatra' get '/' do "Hello World!" end |
ファイルが完成したらサーバを起動させてみましょう。
1 2 3 4 | $ gem install sinatra $ ruby myapp.rb == Sinatra has taken the stage ... >> Listening on 0 . 0 . 0 . 0 : 4567 |
http://0.0.0.0:4567/にアクセスすると「Hello World!」と表示されるアプリができている事が確認できると思います。
では、次に本題に入りましょう。
Herokuアカウントの作成
まずはHerokuにアクセスしてアカウントを作りましょう。 https://www.heroku.com/
「Sign up for free」を押してどんどん進めてください。 メールアドレスの登録、確認が済めば、登録完了です。
登録完了画面でHeroku Toolbeltが表示されるので、ダウンロード、インストールしてください。これはHerokuにデプロイしたりなど、HerokuをPC(Win/Mac/etc)から操作できるようにするためのツール・コマンドセットです。
インストールが終わったら、先ほど作ったアプリケーションのあるフォルダにカレントディレクトリを移動させましょう。($ cd hello
)
そして、Heroku登録完了画面で表示されたコマンド、heroku login
でHerokuにログインしましょう。
1 2 3 | $ heroku login Email: your-email Password (typing will be hidden): your-password |
すると、Herokuとの通信に使う公開鍵・秘密鍵等が自動でアップロードされ、Herokuと通信が行えるようになります。 (既にHerokuアカウントをお持ちの方のPCですと、既に存在していますよとのエラーになります)
[設定] Heroku用コンフィグファイルの作成
Railsアプリケーションの場合にはワンコマンド叩くだけでHerokuにPush(デプロイ・公開)できます。 Sinatraアプリケーションの場合は少しだけ準備・設定が必要になりますので、それを行います。
Herokuへのデプロイの際に、アプリケーションファイルのやりとりにはバージョン管理ソフトウェア、Gitを使います。そのため、Gitの知識が若干必要になりますので、もし全く知らない方はぜひ学習してみてください。 参考:git入門 (全22回) - プログラミングならドットインストール
まず、アプリケーションをGitで管理します。
1 2 3 | $ git init $ git add . $ git commit -a -m "first commit" |
次に、Herokuにデプロイするための設定系ファイルを作成します。 主に以下の3つです。
Procfile
Gemfile
Gemfile.lock
ProcfileはHerokuのサーバが、サーバアプリケーションを動作させる際にどうしたら良いのかを示すためのファイルです。Railsの場合は自動的に生成されています。Sinatraでは自動生成されないので、自前で作る必要があります。
1 2 | Procfile web: bundle exec ruby myapp.rb -p $PORT |
次に、RubyGemsのどのGemを使うのか、どのバージョンを使うのかを管理するファイルを作成します。このファイルもRailsの場合は自動的に生成されています。Sinatraでは自動生成されないので、自前で作る必要があります。
1 2 3 4 |
最後に、Gemfileの中身をインストールします。実際にはすでにSinatraはインストールされているのですが、インストール用のコマンドを実施することで、Gemfile.lockファイルが作成されるため、Gemfileを修正した後は必ず実行するようにしてください。
1 2 3 4 | $ bundle install Fetching gem metadata from https://rubygems.org/........... (省略) Your bundle is complete! |
これでGemfile.lockファイルが作成されました。 最後に、これらをGitのバージョン管理に追加します。
1 | $ git add . |
git status
コマンドで確認してみましょう。
1 2 3 4 5 6 7 8 9 | $ git status # On branch master # Changes to be committed: # (use "git reset HEAD < file >..." to unstage) # # new file: Gemfile # new file: Gemfile.lock # new file: Procfile # |
きちんと必要な3ファイルが作成されていますね。 それでは、これらをGitにコミットして、次の章に進みましょう。
1 | $ git commit -a -m "add heroku config files" |
[デプロイ] Herokuにアプリをデプロイ(公開)
herokuのアカウント作成、ログイン、デプロイするアプリの準備ができました。あとはデプロイするだけです。
新規のアプリのデプロイの場合には下記のコマンドを実行してください。
1 2 3 | $ heroku create $ git push heroku master $ heroku open |
$ heroku create
コマンドでheroku上への新規アプリの作成、アプリ用のGitリモートレポジトリを「heroku」というリモートレポジトリ名で現在のカレントフォルダに追加を一括して行ってくれます。
$ git push heroku master
コマンドでHerokuにデプロイ・公開されます。
一例:
1 2 3 4 | $ git push heroku master (省略) -----> Launching... done, v3 |
$ heroku open
コマンドを実行すると、デフォルトブラウザで、今公開したウェブサービスのページを表示してくれます。
「Hello World!」
先ほどと違ってURLが「http://afternoon-mountain-7821.herokuapp.com」のような、ドメイン形式の物になっているのが分かるかと思います。
以降、ファイルを変更した場合はGitにコミットし、HerokuにPushするだけです。(もしGemfileを変更したらbundle installをお忘れなく)
$ git push heroku master
普及し始めたKeyValueStore、Redisとは?
Redis
Redisはキー・バリュー・ストア型のデータベース&サーバです。
非常に簡単な使用例ですと、set
コマンドでデータをRedisデータベースに設定することができます。
1 | set "LAST_ACCESS_AT" "2013-12-03 11:11:34 +0900" |
その後、いつでも、get
コマンドでデータを取り出すことができます。
1 2 | get "LAST_ACCESS_AT" "2013-12-03 11:11:34 +0900" |
そして、この処理はWebサーバーを複数台を使っている場合でも、1台のRedisサーバにデータが保存されているので、複数台のWebサーバで同じデータを読み書きすることができます。また、Redisは非常に読み書きが高速なサーバです。APIを利用して取得した情報など、取得に時間の掛かる情報をキャッシュすることで、レスポンスを高速に返す事ができるようになります。
今回の記事ではデータを保存しておき、複数ユーザ間で同じデータを使用するために使用します。
Herokuアドオン「Redis To Go」
Redis To Goというクラウドサーバサービスがあります。これは、Redisサーバを簡単に利用、スケールアップさせることができるサービスです。この無料プラン?有料プランを簡単に使用できるアドオンがHerokuにて公開されています。 Herokuアドオン「Redis To Go」 Nanoプラン(無料)
次章で実際に使ってみます。ここで紹介したいのは、Herokuではたくさんのアドオンが公開されており、サーバに必要な機能を非常に容易に得ることができます、ということです。
実際にRedisをローカル・開発環境にインストール
Redisのインストールは下記からダウンロード、実施してください。 Download ? Redis
MacでHomebrewを入れている方は brew install redis
でインストールできます。Windows用のパッケージなどは上記サイトで公開されているソフトウェアでインストールできるかと思います。(推奨はされていないようです)
もう少し詳しく知りたい方は下記などが参考になるかもしれません。 参考: Redis入門 (全14回) - プログラミングならドットインストール
Redisを使ってデータをキャッシュする
RedisをSinatra(ruby)アプリケーションから使う場合は、「Redis」Gemを利用します。インストールはGemfileにRedisを次のように追記し、bundle install
を実施してください。
1 2 3 4 5 |
まずはmyapp.rbサーバーの起動時にRedisサーバへ接続するコードを書きます。
myapp.rb
1 2 | # 0: Redisサーバへ接続(本サーバー起動時) redis = Redis. new host: "127.0.0.1" , port: "6379" |
次に、Redisサーバにアクセスし、キャッシュしておいたデータを取り出します。 今回は最終アクセス日(他ユーザ含む)をキャッシュ、取り出しを行います。 "LASTACCESSAT"というキー(key)で最終アクセス日は保存します。
myapp.rb
1 2 | # 2: Redisサーバーから取得 last_access_at = redis.get( "LAST_ACCESS_AT" ) |
上記でキャッシュしておいたデータを取得できますが、データがなかった時の場合(初回ユーザアクセス時は存在しない)のために、初期値をgetするより前の部分に記載します。
myapp.rb
1 2 | # 1: 最終アクセス日の設定(初期値nil) last_access_at = nil |
また、もし空だった場合には現在時刻を最終アクセス日として表示するためのコードを追記します。
myapp.rb
1 2 3 4 | # 3: もし空なら現在時刻を設定 if last_access_at == nil then last_access_at = Time .now end |
次に、今回のアクセスを最終アクセス日として、Redisに保存(キャッシュ)します
myapp.rb
1 2 | # 4: Redisに保存してある最終アクセス日を更新する redis.set( "LAST_ACCESS_AT" , Time .now) |
最後に、簡単ですが、画面に最終アクセス日を表示するようにします。
myapp.rb
1 | "Hello World!< br />Last access at: " + last_access_at.to_s + "< br />Current access at: " + Time.now.to_s |
これらを全部つなげると下記のようなコードとなります。
myapp.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | require 'sinatra' require 'redis' # 0: Redisサーバへ接続(本サーバー起動時) redis = Redis.new host:"127.0.0.1", port:"6379" get '/' do # 1: 最終アクセス日の設定(初期値nil) last_access_at = nil # 2: Redisサーバーから取得 last_access_at = redis.get("LAST_ACCESS_AT") # 3: もし空なら現在時刻を設定 if last_access_at == nil then last_access_at = Time.now end # 4: Redisに保存してある最終アクセス日を更新する redis.set("LAST_ACCESS_AT", Time.now) # Render "Hello World!< br />Last access at: " + last_access_at.to_s + "< br />Current access at: " + Time.now.to_s end |
これでSinatraアプリケーションでRedisサーバーにデータをキャッシュ、取得して表示・更新する事ができるようになりました。
最後にGitにコミットしておきましょう。
1 | $ git commit -a -m "Add redis-server cache" |
Herokuへのサービスの公開とRedisを使ったキャッシュの利用方法
Herokuに先にデプロイした"Hello World!"と表示するアプリケーションに、Redisでキャッシュする、キャッシュした情報を表示する機能を追加したバージョンをデプロイしましょう。
デプロイにあたって、次の3つの事を行います。
Redisサーバーの用意(Redis To Go)
Redisサーバへの接続方法の設定
デプロイ
Redisサーバーの用意(Redis To Go)
Herokuのホームページからマウス操作のみでRedisサーバを用意することができます。 まず、Redis To GoのHerokuアドオンページにアクセスします。 https://addons.heroku.com/redistogo#nano
プラン「Nano」を選択し、今回作成、デプロイしたアプリケーションを追加先アプリケーションに設定します。その後、「Add Nano for Free」を押して、アプリケーションにAddonを追加してください。
$ heroku addons:add redistogo
というコマンドで追加することもできます。どちらか片方の方法のみ行ってください。
マウス操作を誤ると非常に大きなサイズのプラン・サーバを用意することもできてしまうので、プランがNano(Free)であることは十分確認の上追加してください。
以上でHerokuサーバーからアクセス可能なRedisサーバの設定・準備が整いました。Herokuサイト上から情報を確認できます。
下記コマンドを実行して、Redis To Go接続用ホスト名、ポート番号、ユーザ名、パスワードを取得してください。
1 2 | $ heroku config |
上記のようなフォーマットで表示されます。 意味は次のようになります。
ユーザ名: username
パスワード: password
ホスト名: hostname
ポート番号: port
Redisサーバへの接続方法の設定
上記で取得したRedis To Go接続用の情報をmyapp.rbファイルに記載します。
SinatraアプリケーションをHerokuで動かした場合、
ENV
という変数に各種設定値が入っており、アプリケーション内で利用できます。
今回利用しているRedis To Goの設定値は下記の変数名で保存されています。
1 | ENV [ "REDISTOGO_URL" ] |
Redisサーバへの接続部分を、REDISTOGO_URLが設定されている場合はその設定値を利用し、設定されていない場合にはローカルのRedisサーバに接続するようアプリケーションを修正します。
修正すると下記のようになります。
myapp.rb
1 2 3 4 5 6 | if ENV [ "REDISTOGO_URL" ] != nil uri = URI .parse( ENV [ "REDISTOGO_URL" ]) redis = Redis. new ( :host => uri.host, :port => uri.port, :password => uri.password) else redis = Redis. new host: "127.0.0.1" , port: "6379" end |
また先程までと同様、Gitにコミットしておきましょう。
1 | $ git commit -a -m "Add RedisToGo support" |
デプロイ
HerokuでRedisを使う用意ができましたので、HerokuにアプリケーションをPush、デプロイ・公開します。 確認のために、myapp.rbファイル全体を下記に記載します。
myapp.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | require 'sinatra' require 'redis' # Redisサーバへ接続(本サーバー起動時) if ENV["REDISTOGO_URL"] != nil uri = URI.parse(ENV["REDISTOGO_URL"]) redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password) else redis = Redis.new host:"127.0.0.1", port:"6379" end get '/' do # 1: 最終アクセス日の設定(初期値nil) last_access_at = nil # 2: Redisサーバーから取得 last_access_at = redis.get("LAST_ACCESS_AT") # 3: もし空なら現在時刻を設定 if last_access_at == nil then last_access_at = Time.now end # 4: Redisに保存してある最終アクセス日を更新する redis.set("LAST_ACCESS_AT", Time.now) # Render "Hello World!< br />Last access at: " + last_access_at.to_s + "< br />Current access at: " + Time.now.to_s end |
このファイルと、Gemfile、Gemfile.lock、ProcfileなどGitで管理された各種ファイルを丸ごとHerokuにPushします。
$ git push heroku master
これだけでデプロイは完了です。
$ heroku open
コマンドで反映されたことをブラウザで確認しましょう。
もしエラーなどになるようでしたら、
$ heroku logs --tail
などのコマンドを利用し、Heroku上のログを確認してみてください。
本記事でHerokuへサービスをデプロイする、Redisキャッシュを使う方法を身につけました。 本連載は本記事で終了です。最後までご覧いただき誠にありがとうございました。
この次は、ぜひ自分の頭で何かサービスを考え、作ってみてください。そうすれば、デプロイ(公開)はもう目前です。Herokuやアドオンでサーバの管理・知識は不必要になりました。
ソフトウェアエンジニアが週末だけでサービスを作って運営できる時代です。 今こそサービスを作って公開しましょう!