xxxcaqui.log

ツッコミお待ちしています

Amazon Linuxでrbenvを使ってRuby2.0を入れてみた。

AWSでAmazon Linux上に環境構築してるときに、ちょっとハマったのでメモ。

Amazon LinuxRuby

Amazon Linx(2013.03)にデフォルトで入っているRubyは1.8.7でした。
yumで入れられるのも同じバージョン。

絶望した! 1.9.3すらサクッと入れられないことに絶望した!

というわけで、rbenvを使ってRuby2.0を入れていきます。

必要なパッケージを入れる

Amazon Linuxは最小限のパッケージしか入っていないディストリです。
そのため、Rubyのコンパイルやrbenvのインストールに必要なパッケージも結構不足しているので、ここで入れておきます。

$ sudo yum install gcc git openssl-devel

rbenv, ruby-buildを入れる

rbenv

$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ exec $SHELL -l

ruby-build

$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

Rubyを入れる

Rubyをコンパイルするために、以下のコマンドを実行します。
なお、先程入れたrbenvとruby-buildが正常にインストールされていれば、Tabによる自動補完が有効になっているはずです。

$ rbenv install 2.0.0-p0

上記コマンドを実行すると、

Downloading ruby-2.0.0-p0.tar.gz...
-> http://ftp.ruby-lang.org/pub/ruby/2.0/ruby-2.0.0-p0.tar.gz
Installing ruby-2.0.0-p0...

と表示されてしばらく固まりますが、別窓でtopを実行してみるとCPU使用率が100%になっていて、EC2たんが頑張ってくれているのがわかります。*1

このコンパイル時だけでも、ハイCPUインスタンスとか使うといいと思います。
c1.mediumだと、1時間使っても20円しないので。

入れたRubyを使う

システムがデフォルトで使用するRubyのバージョンを指定します。

$ rbenv global 2.0.0-p0

トラブルシューティング

configure: error: no acceptable C compiler found in $PATH

gccが入っていません。
sudo yum install gcc してください。

The Ruby openssl extension was not compiled. Missing the OpenSSL lib?

openssl-develが入っていません。
sudo yum install openssl-devel してください。

*1:ただし、高確率で「Write failed: Broken pipe」ってなりますw

ELBでNameVirtualHost使ってみた。

AWS ELB(Elastic Load Balancer)を使ってもApacheのNameVirtualHostは機能するのかどうか気になったから、実際に試してみた。

やったこと

EC2を用意する

今回は既に立ち上がっているインスタンスがあったので、それを利用しました。
無ければ新しいEC2インスタンスを立ちあげてください。

ELBを立ち上げてEC2と関連付ける

ELBはManagement Console上部からは選べないので、EC2 Management Consoleの左下の方にあるLoad Balancerというリンクから選べます。

ELB配下のEC2インスタンスでNameVirtualHostの設定をする

NameVirtualHost *:80

<VirtualHost *:80>
  DocumentRoot /var/www/test1
  ServerName   test1.example.com
</VirtualHost>

<VirtualHost *:80>
  DocumentRoot /var/www/test2
  ServerName   test2.example.com
</VirtualHost>

/var/www/test1, /var/www/test2 のディレクトリにindex.htmlを置きます。
後でアクセスした時に違いがわかるよう、中身は違うものにしておきます。

<html>
  <body>
    <h1>test1.example.com</h1>
  </body>
</html>
<html>
  <body>
    <h1>test2.example.com</h1>
  </body>
</html>

NameVirtualHostしたいドメインからELBのDNS NameにCNAMEを張る

ELBへはCNAMEで名前解決します。
AでIPを指定してはいけません。

ブラウザから確認する

NameVirtualHostに設定したドメインをブラウザから叩いてみる。
それぞれのURLで別々のページが表示されれば成功です。

結論

ELBを通してもNameVirtualHostは正常に機能する。

なんか、やっつけエントリになってしまいましたが、ググってもあまりこの手の情報が出て来なかったので、メモとして。

追記

ひとつのEC2インスタンスで複数のアプリケーションを走らせる場合、ヘルスチェックはどうすればいいんだろう?

Yokohama.rbに初参加してきた。

日付的にはもう昨日になっちゃいましたが、Yokohama.rbに参加してきました。

「Yokohama.rbは参加しやすい」

先日、Shibuya.rbで「初めての人も参加しやすい」との噂を聞いていたYokohama.rbですが、たしかに初めに簡単な自己紹介があったり、レシピブック読書会があって「もくもくって言われてもやることない!」みたいな事態に陥らなかったりと、参加しやすい感じでした。

レシピブックを読んで

使用したレシピブックはこれ。

この本の配列のあたりをやりました。

レシピブックに載っているメソッドのほとんどは既知のものでしたが、「このメソッド使うよりこうやったほうがいよ」みたいな話を聞けたり、あるメソッドが他のどの言語由来なのかという話を聞けたりと、有意義な時間だったと思います。

あと、ブラウザごとのJSのUndefinedの取り扱い方の違いに( ゚д゚)ってなったり、@さんのVim力すげーってなったり。

懇親会

懇親会にも参加させてもらいました。
今回は僕含め、初参加の人が結構いたと思うのですが、なんと参加者全員が懇親会にも参加。

俺は懇親会中何をしてたかというと、美味しい中華を食べつつ、アルゴリズム的な話に聞き耳を立てて「うわーわかんねー!」みたいな。

あと、初めの自己紹介だけでは他の参加者の方の名前を覚えられなかったのですが、懇親会終了後は近くに座っていた方の名前はだいたい覚えました。
もしかして、懇親会って非常に重要なのでは? との思いを新たにしました。

感想

例のごとく、今回も「えっ? 俺のスキル、しょぼすぎ……?」って感じになりましたが、中でも一番ダメージを受けたのが某氏の

いやー、こういうところに来ると、自分が井の中の蛙だと思いますよねー。

みたいな発言(うろ覚え)。

「いや、俺からしたらあなたも十分すごいんですけど!!」みたいな。
俺なんて井の中のミジンコですね。

とはいえ、情熱プログラマーにも「一番へたくそでいろ」みたいなことが書かれてましたし、この立場を存分に満喫させてもらおうと思います。*1

今後もYokohama.rb参加させていただきたいと思うので、よろしくお願いします!*2

*1:ご迷惑おかけします。

*2:早速、来月はちょっと行けなさそうですがw

Rails上で動くCMS LocomotiveCMSを使ってみる。

近々、CMSを構築する必要が出てきたのでLocomotiveを使ってみた。

Locomotiveを選んだ理由は大きく以下の3つ。

  1. Rubyで書かれている
  2. Herokuで動かせる
  3. 管理ページが日本語対応している*1

後々、大きく手を加える予定なので「使い慣れた環境で動くもの」という点を重視して選びました。

Locomotiveとは

LocomotiveはRailsCMSとして使うためのgemです。
オープンソースであり、開発はGitHub上で行われています。

https://github.com/locomotivecms/engine

依存アプリケーションのインストール

Locomotiveは以下の4つに依存しています。

RubyRailsは既にインストールされていると思うので、MongoDBとImagemagickを入れます。*2

Ubuntuの場合こんな感じ。

$ sudo apt-get install mongodb-server imagemagick

Rails, Locomotiveを使ってCMSを構築する

Railsアプリケーションの作成

実際にCMSとして使用するRailsアプリケーションを作成していきます。
ただ、LocomotiveはDBにMongoDBを使用するため、ORMとしてActiveRecordを使用出来ません。そこでActiveRecordを除いた状態でRailsアプリを作成します。

$ rails new new_loco --skip-active-record --skip-test-unit --skip-javascript --skip-bundle

LocomotiveではActiveRecordの代わりにMongoidが使用されます。*3

Gemfileを設定してgemをインストールします。

#~/new_loco/Gemfile
gem 'locomotive_cms', '~> 2.0.1', require: 'locomotive/engine'
gem 'therubyracer', '>= 0.8.2' # Linux only

gem 'unicorn', group: :development
gem 'thin', group: :production

group :assets do
  gem 'compass-rails',  '~> 1.0.2'
  gem 'sass-rails',     '~> 3.2.4'
  gem 'coffee-rails',   '~> 3.2.2'
  gem 'uglifier',       '~> 1.2.4'
end
$ bundle install

Locomotiveのengine用の設定ファイルを生成します。

$ bundle exec rails generate locomotive:install

ただし、上記コマンドの実行が2回目以降の場合、データベースの名前がぶつかって、

==  MakeEditableElementsConsistent: migrating ==
[old_app_name] index (de)
rake aborted!
An error has occurred, all later migrations canceled:

undefined method `walk' for nil:NilClass

とか怒られます。

したがって、先にconfig/mongid.ymlの設定を書き換えてください。

development:
  <<: *defaults
  database: locomotive_dev # Overwite this

locomotive:installコマンドが完了すると、

The Locomotive Engine has been correctly
installed in your Rails application.

  1. Edit the main config files:
    - config/initializers/locomotive.rb
    - config/initializers/carrierwave.rb
    - config/initializers/dragonfly.rb
    - config/mongoid.yml
    - config/devise.yml
    - config/routes.rb

  2. Launch the server
    > bundle exec unicorn_rails

  3. Open your browser
    > open localhost:8080

  4. Follow the installation wizard steps
  5. Enjoy !

と表示されてLocomotiveを使用できるようになります。

$ bundle exec unicorn_rails

して、localhost:8080にアクセスしてみてください。

初期設定画面が立ち上がります。

f:id:xxxcaqui:20130410224428p:plain

Herokuにデプロイする

Heroku上にアプリケーションを作成する

Heroku上にアプリケーションを作成し、bundle installのオプションを設定しておきます。

$ heroku create new-loco
$ heroku config:add BUNDLE_WITHOUT=development:test

Heroku用のgemを入れる

LocomotiveはそのままだとHeroku上で動かないので、Herokuで動かすためのgem locomotive-herokuを入れます。

#Gemfile
gem 'locomotive-heroku', '~> 0.0.2', require: 'locomotive/heroku'
$ bundle install

そして、設定ファイルに記述を追加。
アプリケーション名はまだしも、API keyは他人に見られたくないため、Herokuの環境変数を使います。

#config/initializers/locomotive.rb
config.hosting = {
  target: :heroku,
  api_key: ENV["HEROKU_API_KEY"],
  app_name: ENV["HEROKU_APP_NAME"]
}
$ heroku config:set HEROKU_API_KEY=< your api key >
$ heroku config:set HEROKU_APP_NAME=< your app name >

Amazon S3情報の設定

Herokuアプリケーションのローカルストレージは永続性が保証されないので、ストレージとしてS3を使います。

このあたりはさっき入れたlocomotive-herokuが対応してくれているので、Herokuの環境変数にS3の情報を設定するだけで大丈夫です。*4

$ heroku config:add S3_KEY_ID=<your s3 key id>
$ heroku config:add S3_SECRET_KEY=<your s3 secret key>
$ heroku config:add S3_BUCKET=<your s3 bucket name>
$ heroku config:add S3_BUCKET=<your s3 zone>

S3のゾーンはわかりにくいですが、AWSにログインしてから

S3 Management Console > Properties > Static Website Hosting > Endpoint

で見られます。*5

MongoDBアドオンの設定

HerokuのデフォルトDBはPostgreSQLなので、MongoDBを使えるようにadd-on「MongoHQ」を追加します。

$ heroku addons:add mongohq:sandbox

DB設定ファイルのherokuのuri:をアンコメントし、デフォルトになっているbushidouri:をコメントアウトします。

#config/mongoid.yml
production:
  # heroku
  uri: <%= ENV['MONGOHQ_URL'] %>

  # bushido (mongohq_url will also work)
  # uri: <%= ENV['MONGODB_URL'] %>

ここでの環境変数はadd-on追加時に自動的に設定されています。*6

メールアドオンの設定

メール送信用のadd-on「SendGrid」も一緒に設定しておきます。

$ heroku addons:add sendgrid:starter

メールの設定を行います。
ここでの環境変数も自動的に設定されています。

#config/environments/production.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address:        "smtp.sendgrid.net",
  port:           25,
  authentication: :plain,
  user_name:      ENV["SENDGRID_USERNAME"],
  password:       ENV["SENDGRID_PASSWORD"],
  domain:         ENV["SENDGRID_DOMAIN"]
}

precompile設定

このままHerokuにデプロイすると、asset pipeline周りで弾かれました。

Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       Failed to connect to a master node at localhost:27017

したがって、面倒ですがprecompileしてからデプロイすることにします。

デプロイ時のprecompileを無効化。*7

#config/application.rb
module NewLoco # your app name
  class Application < Rails::Application
    config.assets.initialize_on_precompile = false
  end
end

precompileを実行。

$ bundle exec rake assets:precompile

これで、コンパイル済みのassetsが生成され、デプロイできるようになります。

やったね!

おまけ:Wagonのインストール

LocomotiveにはWagonというユーティリティツールが存在します。

$ gem install locomotivecms_wagon

Locomotiveサイトの作成

先程、インストールしたWagonを使って新規Locomotiveサイトを作成します。

$ wagon init first_loco_site --template bootstrap

これで、Twitter Bootstrap適用済みのfirst_loco_siteという名前の新規サイトが作成されます。*8

なお、現時点でのテンプレートは以下のものがあります。*9

blank 最小限のファイル構成でサイトを作成します。
bootstrap Twitter Bootstrapを使用してサイトを作成します。
foundation Foundationを使用してサイトを作成します。
unzip zip圧縮されたLocomotiveサイトを展開します。*10

サイトが作成できたら、必要なgemをインストールし、ついでにGitでバージョン管理しておきます。

$ cd first_loco_site
$ bundle install
$ git init .
$ git add .
$ git commit -m 'First commit.'

作成したサイトの確認

ここまでで作ったサイトを確認しておきます。

$ buncle exec wagon serve

上記のコマンドでサーバが立ち上がり、0.0.0.0:3333からアクセスできるようになります。*11

f:id:xxxcaqui:20130410190147p:plain

また、app/views/index.liquid.hamlを編集すると、サンプルページが変更されます。サーバの再起動は必要ありません。なお、ログは log/wagon.logに吐き出されます。

*1:ウソです。i18n対応していたので日本語を追加しました。

*2:MongoDBやImagemagickもわりとインストール済みだったりします。

*3:ちなみに、MongoDBはRDBMSではなくドキュメント指向のいわゆるNoSQLなので、ORMではなくODM(Object-Document Mapper)です。

*4:config/carrierwave.rbを設定すれば、CarrierWaveでアクセスできる他のストレージも使用できるみたいです。

*5:見つけるまで結構かかりましたw

*6:heroku config:getで確認できます。

*7:http://guides.rubyonrails.org/asset_pipeline.html

*8:途中でhamlを使うかどうか聞かれるので、テキトーに答えてください。

*9:wagon list_templateコマンドで見れます。

*10:コマンド実行後、zipのパスを要求されます。ローカルまたはhttp, https, ftpで取得可能なURLを指定できます。

*11:RFC1700によると0.0.0.0は「This host on this network. Can only be used as a source address.」とあり、ホストのアドレスを示すらしい。本来は送信元アドレスとしてしか利用できないようだが、Linuxではlocalhostと同義のようでlocalhost:3333でもアクセスできます。ネットワークの勉強しないと。

Herokuへのデプロイについてまとめてみる

ここのところ、ちょいちょいHerokuにアプリを上げてるにも関わらず、コマンド類がなかなか覚えられないのでざくっとまとめてみる。

前提

  • アプリケーションがGitでバージョン管理されている。

Heroku用のgemを入れる

gem install heroku

これでターミナルからherokuコマンドが使えるようになります。

Gemfileの設定

HerokuのデフォルトDBはPostgreSQL*1なので、Postgre用のgemを入れる。

また、そのままだと「SQLite3無理っす!」みたいな感じで怒られるので、本番環境にはSQLite用のgemを入れないようにする。

gem "pg", group: :production
gem "sqlite3", group: :development

その後、忘れずにbundle installして、git commit。

Heroku上にアプリケーションを作成する

heroku apps:create

デフォルトではランダムなアプリケーション名が与えられるので、任意の名前に変更します。*2

heroku apps:rename your_app_name

2013-04-30追記

上の2つのコメントですが、次のコマンド一発でいけます。

heroku apps:create your_app_name

さあ、デプロイ!

ここが一番簡単。

git push heroku master

git pushするだけでデプロイ出来るなんてHerokuさんステキ! 抱いて!!

その他

Heroku環境でのコマンド実行

rakeコマンドなどをHerokuの環境で行うためには、heroku runコマンドを使用します。

たとえば、データベースの変更を伴うデプロイを行った場合のマイグレーション用コマンドは以下の通り。

heroku run rake db:migrate

メンテナンスモード

Herokuでは「メンテナンス中」みたいなページをコマンドひとつで出すことが出来ます。

heroku maintenance:on

緊急メンテナンスでユーザのアプリケーション利用を止めたい場合やデプロイ時にデータの不整合を起こしたくない場合などに利用できます。

ちなみに、メンテナンスモードからの脱出は次の通り。

heroku maintenance:off

ロールバック

デプロイしたアプリケーションに不具合があって以前のバージョンに戻したい場合。

heroku releases

で今までのデプロイ一覧が表示されるので、左側にあるバージョン番号を指定して

heroku releases:rollback v8

のようなコマンドを実行すると、指定したバージョンまでアプリケーションがロールバックされます。

「バージョン管理」ツールの面目躍如といった感じですね。

ログの監視

Herokuのサーバに直接ログインすることは出来ないので、ログを見るためには次のコマンドを打ちます。*3

heroku logs -t

これで、アプリケーションによって出力されるログをリアルタイムで追跡することが出来るようになります。*4

参考

このエントリを書くにあたって、WEB+DB vol.71を参考にしました。*5

*1:読み方「ぽすぐれ」でおk?

*2:アプリケーション名はHeroku全体で一意である必要があるので、既に使われている名前は弾かれます。

*3:ちなみに、オプションの-tは付けなくても一応動きました。

*4:tail -f log/production.log みたいな感じ。

*5:というか、ほぼ丸パクリです。