写経環境を、vagrant-berkshelf から Vagrant + knife-solo + Berkshelf へと変更した

以前、GDG信州でvagrant-berkshelfを使った写経環境構築の発表をしましたが、その数日後にvagrant-berkshelfが非推奨になってしまいました*1
今のところは使えるものの、将来的なことも考えて、手元にある写経用の環境を Vagrant + knife-solo + Berkshelf へと更新しました。

環境


ちなみに、VMへのCookbook転送については、

のようにいくつか方法があったものの、今回はVagrantに任せることにしました。


なお、WindowsでのCookbook転送については、knife-soloのGitHubのIssueにMilestone(0.5.0)と書かれていました。
Provide better help if rsync isn't available · Issue #167 · matschaffer/knife-solo · GitHub


また、構築したものはGitHubにて公開しておきました。
thinkAmi/syakyo_env-ruby · GitHub



流れ

knife soloとBerkshelfのインストール

knife-soloとBerkshelfはBundlerで入れることにするため、Gemfileを作成します。
d:\hoge\Gemfile

source 'https://rubygems.org'

gem "knife-solo"
gem "berkshelf"

gem "win32-api", "~> 1.5.1", platforms: [:mingw, :x64_mingw]


なお、knife-solo 0.4.1の場合、何も指定しないとwin32-apiが1.4.8で入りますが、そのままではknife-solo実行時に以下のエラーが出ます。そのため、明示的にwin32-apiのバージョンを指定しておきます。

d:\hoge\fuga>bundle exec knife solo init chef-repo
DL is deprecated, please use Fiddle
d:/Develop/env/knife/vendor/bundle/ruby/2.0.0/gems/win32-api-1.4.8-x86-mingw32/lib/win32/api.rb:2:in `require': 126: 指定されたモジュールが見つかりません。   - d:/Develop/env/knife/vendor/bundle/ruby/2.0.0/gems/win32-api-1.4.8-x86-mingw32/lib/win32/ruby19/win32/api.so (LoadError)

また、念のためplatformsの指定もしておきました。platformsに指定するシンボル名は、以下を参考にしました。
Gemfile(5) - A format for describing gem dependencies for Ruby programs



Bundlerでパスを指定してローカルインストールします。

d:\hoge>bundle install --path vendor/bundle
DL is deprecated, please use Fiddle
Fetching gem metadata from https://rubygems.org/........
Fetching additional metadata from https://rubygems.org/..
Resolving dependencies...
〜略〜
Installing win32-api (1.5.1)
〜略〜
Installing knife-solo (0.4.1)
Using bundler (1.5.3)
Your bundle is complete!
It was installed into ./vendor/bundle
Post-install message from knife-solo:
Thanks for installing knife-solo!
If you run into any issues please let us know at:
  https://github.com/matschaffer/knife-solo/issues

If you are upgrading knife-solo please uninstall any old versions by running `gem clean knife-solo` to avoid any errors.

See http://bit.ly/CHEF-3255 for more information on the knife bug that causes this.


knifeの設定をします。色々と聞かれますが、今回はすべてEnterで進めます。

d:\hoge>bundle exec knife configure
DL is deprecated, please use Fiddle
WARNING: No knife configuration file found
〜略〜
Configuration file written to C:/Users//.chef/knife.rb
写経環境向けのCookbook作成

knifeを使ってリポジトリを作成します。knifeはBerkshelfと連携ができるようなので*2、同時にBerksfileも作成されます。

d:\hoge>mkdir fuga
d:\hoge>cd fuga
d:\hoge\fuga>bundle exec knife solo init chef-repo
DL is deprecated, please use Fiddle
Creating kitchen...
Creating knife.rb in kitchen...
Creating cupboards...
DL is deprecated, please use Fiddle
Setting up Berkshelf...


knifeを使ってCookbookのひな形を作ります。今回は、以下の内容でひな形を作ります。

  • Cookbook名: base
  • Cookbookの保存先: site-cookbooksディレクトリの下
d:\hoge\fuga>pushd chef-repo
d:\hoge\fuga\chef-repo>bundle exec knife cookbook create base -o site-cookbooks
DL is deprecated, please use Fiddle
** Creating cookbook base
** Creating README for cookbook: base
** Creating CHANGELOG for cookbook: base
** Creating metadata for cookbook: base


続いて環境用のレシピを編集します。内容は以下の通りです。

  • Ubuntuのみの設定
  • Gitの最新版をPPAからインストールする*3
  • Node.js、SQLiteBrowserをインストールする
  • Gitのブランチをターミナルに表示する
  • .gemrcを作成する

d:\hoge\fuga\chef-repo\site-cookbooks\base\recipes\default.rb

return unless node['platform'] == "ubuntu"

apt_repository 'git' do
    uri 'http://ppa.launchpad.net/git-core/ppa/ubuntu'
    distribution node[:lsb][:codename]
    components [:main]
    keyserver 'keyserver.ubuntu.com'
    key 'E1DF1F24'
    notifies :run, 'execute[apt-get update]', :immediately
end
package 'git'

package "nodejs"

package "sqlitebrowser"


script "show_git_branch" do
  interpreter "bash"
  user        "root"
  code <<-'EOL'
    wget https://raw.github.com/git/git/master/contrib/completion/git-completion.bash -P /home/vagrant
    chmod -R 777 /home/vagrant/git-completion.bash
    echo source /home/vagrant/git-completion.bash >> /home/vagrant/.bashrc
    echo GIT_PS1_SHOWDIRTYSTATE=true >> /home/vagrant/.bashrc

    echo -n export PS1=\' >> /home/vagrant/.bashrc
    echo -n '\[\033[01;32m\]\u@\[\033[01;33m\] \w$(__git_ps1) \[\033[01;34m\]\$\[\033[00m\] ' >> /home/vagrant/.bashrc
    echo \' >> /home/vagrant/.bashrc

    source /home/vagrant/.bashrc
  EOL
end


script "create_gemrc" do
  interpreter "bash"
  user        "root"
  code <<-'EOL'
    echo 'install: --no-rdoc --no-ri' >> /home/vagrant/.gemrc
    echo -n 'update:  --no-rdoc --no-ri' >> /home/vagrant/.gemrc
    chmod -R 777 /home/vagrant/.gemrc
  EOL
end


上記の設定の他、サードパーティのCookbookを利用するため、knife solo init で作成したBerksfileを編集します。
d:\hoge\fuga\chef-repo\Berksfile

site :opscode

cookbook 'apt'
cookbook 'ruby_build'
cookbook 'rbenv', github: "fnichol/chef-rbenv"
cookbook 'sublime-text', github: 'ephess/sublime-text'


vagrant-berkshelfプラグインが無いため、事前にBerkshelfを実行してサードパーティのCookbookを取得しておきます。

d:\hoge\fuga\chef-repo>bundle exec berks install --path cookbooks
DL is deprecated, please use Fiddle
DL is deprecated, please use Fiddle
Installing apt (2.3.8) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing ruby_build (0.8.0) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Installing rbenv (0.7.3) from github: 'fnichol/chef-rbenv' with branch: 'master' over protocol: 'git'
Installing sublime-text (0.1.0) from github: 'ephess/sublime-text' with branch:'master' over protocol: 'git'
Installing java (1.19.2) from site: 'http://cookbooks.opscode.com/api/v1/cookbooks'
Vagrant設定

Vagrantfileを作成します。

d:\hoge\fuga\chef-repo>popd
d:\hoge\fuga>vagrant init
A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `vagrantup.com` for more information on using Vagrant.


作成したVagrantfileを編集します。chef.cookbooks_pathで、Cookbookがある相対パスを指定します。
d:\hoge\fuga\Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.hostname = "foo"
  
  config.vm.box = "ubuntu120403ja"
  config.vm.network :private_network, ip: "192.168.33.10"

  config.vm.provider :virtualbox do |vb|
    vb.gui = true
  end

  config.omnibus.chef_version = :latest


  config.vm.provision :chef_solo do |chef|
    chef.json = {
      rbenv: {
        user_installs: [{
          user: "vagrant",
          rubies: ["2.0.0-p451"],
          global: "2.0.0-p451",
          gems: {
            "2.0.0-p451" => [
              { name: "bundler"
              }
            ]
          }
        }]
      }
    }

    chef.cookbooks_path = ["./chef-repo/cookbooks", "./chef-repo/site-cookbooks"]


    chef.run_list = [
      "apt",
      "base",
      "ruby_build",
      "rbenv::user",
      "sublime-text"
    ]
  end
end
起動と確認

vagrant upで環境を構築します。

d:\hoge\fuga>vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
〜略〜
[2014-02-26T08:27:53+00:00] INFO: execute[apt-get update] sending run action to
execute[apt-cache gencaches] (immediate)
[2014-02-26T08:27:53+00:00] INFO: execute[apt-cache gencaches] ran successfully
[2014-02-26T08:28:09+00:00] INFO: Chef Run complete in 841.560946263 seconds
[2014-02-26T08:28:09+00:00] INFO: Running report handlers
[2014-02-26T08:28:09+00:00] INFO: Report handlers complete


ターミナルで環境が構築されているかを確認します。

vagrant@ ~ $ rbenv versions list
  system
* 2.0.0-p451 (set by /home/vagrant/.rbenv/version)
vagrant@ ~ $ git --version
git version 1.9.0
vagrant@ ~ $ subl --version
Sublime Text 2 Build 2221


以上で完成です。

Vagrantの既存Boxに日本語環境 + GuestAdditions + Chefを入れ、新しいBoxとして追加する

写経環境用のVagrant Boxとして、以前veeweeで作成したもの を使っていましたが、

  • 日本語環境になっていない
    • 日本語環境を手動で作ってた
  • GuestAdditionsやChefが入っていない
    • 起動時に時間がかかる

というモノでした。


しかし、最近そのBoxを使う機会が増え、毎回上記の不足している分の作業を行っていると、それらが整備済の環境をお手軽に作りたくなりました。
そこで、veeweeやChefで設定するのではなく、以下を参考にして vagrant package を使って新しいBoxとして追加することにしました。
プラグインのせいで遅くなったvagrant upを高速化する方法 - DQNEO起業日記

環境

Vagrant upまで

上記を参考に、Vagrantfileを作成し vagrant up します。


自分の場合は、Boxとして追加済の「ubuntu120403」と、Railsチュートリアル用の写経環境作成時に使ったVagrantfile を流用して作りました。
また、ホストがWindowsなので、vagrant up時にGUI表示するようにしました。



日本語環境の設定

UbuntuのJapanese Teamによる追加パッケージの追加

以下を参考に、方法2の3.まで作業を行います。
Ubuntuの日本語環境 | Ubuntu Japanese Team



Language Support の設定

以下を参考に、Language Supportの設定を行います(13.10版ですが似たような感じでした)。
Ubuntu 13.10 その7 - 日本語環境の構築・Ubuntu Japanese Teamのリポジトリーを追加する - Ubuntu kledgeb


自分の行った流れは、以下の通りです。

  1. SystemSettings > Language Support
  2. Languageタブ
    1. Install/Remove Languages...ボタン
    2. Japaneseにチェックし、Apply Changesボタン
    3. Japaneseをドラッグして、先頭へ
    4. Apply System-Wideボタン
  3. Regional Formatsタブ
    1. 日本語を選択
    2. Appli System-Wideボタン
再起動

作業が終わったら、vagrant reload で再起動します。
再起動時にディレクトリ名の変更を聞かれますが、そのままにしておきます。



キーボードレイアウトの設定

ホストが日本語レイアウトなので、Box側も日本語レイアウトにしておきます。

  1. システム設定 > キーボードレイアウト
  2. +ボタン
  3. 日本語(OADG 109A) を選択
  4. 追加ボタン
  5. 日本語を一番上にする(上<ボタン)


以上でGUI上の作業は終わりなので、 vagrant halt で停止しておきます。



新しいBoxの追加

上記で作成した環境をBox化します。各コマンドとも時間がかかりますが、放置して気長に待ちます。

vagrant package
vagrant box add ubuntu120403ja package.box

なお、必要に応じて、outputオプションを付けて vagrant package時にできるboxの名前を変更します。


あとは、Vagrantfile内で、

config.vm.box = "ubuntu120403ja"

と指定しておけば、 vagrant up時に利用できます。

The RSpec Book用にVagrant環境を作成し、写経してみた

RSpecの使い方に慣れるため、評判の良い「The RSpec Book」を写経しました。


手を動かすチュートリアルとしては、Codebreakerというゲームと、Railsの2種類あり、それぞれの作り方がとても参考になりました。
特に、リファクタリングの方法や考え方まで記載されていたので、独学で進めている自分にはありがたかったです。


ただ、本を写経するのに必要な環境が少々古かったことから、Vagrantで環境を作ってから写経をやりましたので、その時の内容をメモしておきます。

The RSpec Book (Professional Ruby Series)

The RSpec Book (Professional Ruby Series)



写経の方法

以下を参考に(というかそのまま)、git(と途中からbranch)を使って写経しました。
技術書の写経 - wyukawa’s blog

1. git checkout -b ブランチ名 で章ごとにブランチを切ってコミットする
2. 章が終わったら、 git checkout master でmasterに戻る
3. git merge ブランチ名 でマージする
4. git tag タグ名 でタグをつける
5. 上記1.〜4.を繰り返す
全て終わったら、git push で --allや--tagsオプションを使って、githubへとpush

写経時の補足

19章以降で使うGemfileについては、以下の記事がとても参考になりました。ありがとうございました。
今頃「The RSpec Book」の第19章(Railsのテスト)以降を試すには - Qiita


また、本の19章以降でRailsを扱いますが、さらっと書いてあったところでもRails力がない自分には少々悩んだため、その部分を補足しておきます。

p364 の補足

本文以外に、「app/model/message.rb」の「validates_presence_of」へ「:text」を追加しないとエラーになります。

class Message < ActiveRecord::Base
  validates_presence_of :title, :text
end
p371 補足

user_example*_spec.rb等は、元々あるuser_spec.rbに上書きして進めることにします。説明のためにファイル名をつけていただけと考えました。



p375 マイグレーションの補足
$ script/rails generate migration AddSenderidToMessage sender_id:integer
      invoke  active_record
      create    db/migrate/20140108210604_add_senderid_to_message.rb

$ bundle exec rake db:migrate(in /home/vagrant/rspec/messages)
==  AddSenderidToMessage: migrating ===========================================
-- add_column(:messages, :sender_id, :integer)
   -> 0.0010s
==  AddSenderidToMessage: migrated (0.0013s) ==================================

$ bundle exec rake db:test:prepare(in /home/vagrant/rspec/messages)
p378 マイグレーションの補足
$ script/rails generate model Subscription subscription_id:integer
      invoke  active_record
      create    db/migrate/20140108212337_create_subscriptions.rb
      create    app/models/subscription.rb
      invoke    rspec
      create      spec/models/subscription_spec.rb

$ script/rails generate migration AddSubscriptionidToUser subscription_id:integer
      invoke  active_record
      create    db/migrate/20140108212429_add_subscriptionid_to_user.rb

$ bundle exec rake db:migrate
(in /home/vagrant/rspec/messages)
==  CreateSubscriptions: migrating ============================================
-- create_table(:subscriptions)
   -> 0.0012s
==  CreateSubscriptions: migrated (0.0014s) ===================================

==  AddSubscriptionidToUser: migrating ========================================
-- add_column(:users, :subscription_id, :integer)
   -> 0.0009s
==  AddSubscriptionidToUser: migrated (0.0011s) ===============================

$ bundle exec rake db:test:prepare
(in /home/vagrant/rspec/messages)

ホスト環境とゲスト環境

ホスト環境

Cookbookの依存などの解決が手間なので、Berkshelfを使ってVagrantfileなどを作成します。
なお、全体的にバージョンが少々古いですが、写経がメインなので今回は特に気にしないことにします。

ゲスト(写経)環境
  • Ubuntu 12.04.3のBox (veeweeで作成したBox、記事はこちら)
  • rbenvへRuby1.8.7を入れる
  • vagrant up時に入れておくgem
    • Bundler 1.0.22
    • Rspec 2.0.0
    • Cucumber 0.9.2
  • Sublime Textをインストール(Githubにあったcookbookを利用)
  • Terminalでgitのbranchが見えるように、.bashrcを編集
  • 日本語化は特にしない (必要であれば、vagrant up後に手動で構築)


なお、Berkshelfで作成した写経用のファイルはGitHubに上げておきました。
thinkAmi/the_rspec_book-env · GitHub



ゲスト環境の構築手順

忘れないように手順を残しておきます。

Vagrantプラグインをインストール
d:\TheRSpecBook>vagrant plugin install vagrant-omnibus
Installing the 'vagrant-omnibus' plugin. This can take a few minutes...
Installed the plugin 'vagrant-omnibus (1.2.1)'!

d:\TheRSpecBook>vagrant plugin install vagrant-berkshelf
Installing the 'vagrant-berkshelf' plugin. This can take a few minutes...
Installed the plugin 'vagrant-berkshelf (1.3.7)'!
BundlerでBerkshelfをローカルインストール

Gemfileを作成します。

d:\TheRSpecBook>bundle init
Writing new Gemfile to d:/TheRSpecBook/Gemfile


Gemfileへ記入します。今回のBerkshelfはGitHubではなくRubyGemsにアップされているものを使用しました。

source "https://rubygems.org"

gem 'berkshelf'


Berkshelfをローカルインストールします。

d:\TheRSpecBook>bundle install --path vendor/bundle
〜省略〜
Your bundle is complete!
It was installed into ./vendor/bundle
Berkshelfの実行と各種ファイルの作成
d:\TheRSpecBook>bundle exec berks cookbook the_rspec_book-env
〜省略〜
      create  the-rspec-book/Vagrantfile


各種ファイルのひな形ができたため、以下のファイルを修正します。

  • Berksfile
  • Vagrantfile
  • recipes/default.rb


Berkshelf v3系から記載方法が変更になるようですが、今のところv3系のbetaがとれたリリースはされていないこともあり、v2系の記述で必要なcookbookを指定しておきます。


Vagrantfileには、rbenvに入れるgemの指定と、使用するcookbookの指定をしておきます。
Vagrant用のBoxはローカルにある前提ですが、起動時にWebよりダウンロードすることもできます。


recipes/default.rbには、以下の2つを行うための内容を記載しておきます。

  • GitのbranchをTerminalへ表示
  • Cucumberの0.9.2をUbuntu12.04.3へ入れるための設定


GitのbranchをTerminalへ表示する方法は以下を参考にして記載しました。
ubuntu terminal にgit のブランチ名を表示 - kyos1704活動記

script "show_git_branch" do
  interpreter "bash"
  user        "root"
  code <<-'EOL'
    wget https://raw.github.com/git/git/master/contrib/completion/git-completion.bash -P /home/vagrant
    chmod -R 777 /home/vagrant/git-completion.bash
    echo source /home/vagrant/git-completion.bash >> /home/vagrant/.bashrc
    echo GIT_PS1_SHOWDIRTYSTATE=true >> /home/vagrant/.bashrc

    echo -n export PS1=\' >> /home/vagrant/.bashrc
    echo -n '\[\033[01;32m\]\u@\[\033[01;33m\] \w$(__git_ps1) \[\033[01;34m\]\$\[\033[00m\] ' >> /home/vagrant/.bashrc
    echo \' >> /home/vagrant/.bashrc

    source /home/vagrant/.bashrc
  EOL
end


Rubyのバックスラッシュ記法を有効にしないよう、ヒアドキュメントの開始をシングルクオートで囲っています。
リテラル


また、.bashrcへ出力をワンライナーで記載する方法が分からなかったので、上記のようにシングルクオートを出力する前後で分割しました。


その他、.bashrcに関して、以下を参考にしました。


CucumberをUbuntu12.04.3へ入れるための設定は、Ubuntuに入っているgcc-4.6ではcucumber 0.9.2をインストール時にエラーとなるため、以下を参考に、gcc-4.5へシンボリックリンクを変更します。
[help]Error Installing Gherkin · Issue #139 · cucumber/gherkin · GitHub

package "gcc-4.5" do
  action :install
end

script "change_gcc45" do
  interpreter "bash"
  user        "root"
  code <<-'EOL'
    rm /usr/bin/gcc
    ln -s /usr/bin/gcc-4.5 /usr/bin/gcc
  EOL
end


あとはvagrant upして環境構築は完了です。
たまにChefのCookbookが適用されないこともありましたが、その時はvagrant destroyしてからupすることで適用されたりしますので、あまり気にしないことにしました。

d:\TheRSpecBook>cd the_rspec_book-env
d:\TheRSpecBook\the_rspec_book-env>vagrant up

Windows7で Capistrano3 + Berkshelf + Vagrant を使って、Padrinoアプリのデプロイ・マイグレーション・起動をしてみた

以前、Capistrano3.x にてSinatraアプリをVagrant上へデプロイしてみました。
そこで今回は、PostgreSQLを使用するPadrinoアプリをVagrant上へデプロイしてみました。
なお、Vagrant上を開発的なstaging環境と考えたため、セキュリティとかはあまり考慮していません。

環境

環境の構築方法などは、以前の記事の通りです。


なお、db:seedはアプリのソースコードを変更する必要がありそうだったため、起動の確認はしたもののコメントアウトしてあります。


また、実際のBerksfileやVagrantfile、Capistrano関連のファイルは、GitHubに置いておきました(「Padrino_PostgreSQL」ディレクトリ配下)。
thinkAmi/Capistrano_v3-example · GitHub



Berkshelf + Vagrantまわりの設定

Berksfileの修正

今回はPostgreSQLを使うため、関係するcookbook「postgresql」「database」を追加しておきます。



Vagrantfileの修正
  • ホストOSからゲストOSにフォワードするポートを設定

Padrinoはデフォルトではポート3000を使用するため、フォワードするポートを変更しておきます。

  • Rubyのバージョン指定

アプリでRubyを1.9系指定しているため、rbenvに1.9系だけ、gemはbundlerだけを入れておきます。

アプリで使うユーザとパスワードを設定します。なお、ここで指定しているpasswordはPostgreSQL上のpostgresユーザのパスワードであり、UNIXのpostgresユーザではありません*1


他に、以下のようなこともあるので、念のため「dir」も明示しておきます。
ubuntu 12.04 - Installing PostgreSQL 9.2 with Chef postgresql - Stack Overflow


pg_hbaについては、必要に応じて以下を参考に記載します。
postgresql - chef-solo + postgres result in invalid pg_hba.conf - Stack Overflow



  • run_listの設定

PostgreSQL用に「postgresql::apt_pgdg_postgresql」「postgresql::server」「database::postgresql」と、実際のデータベースを生成する自作のレシピ「hoge::postgresql」を追加します。


なお、「database::postgresql」ではなく「database」を指定した場合、「vagrant up」時に以下のエラーが出るので注意します。

[2013-11-20T22:26:31+00:00] ERROR: postgresql_database[herokudev] (hoge::postgresql line 10) had an error: LoadError: cannot load such file -- pg

参考:https://github.com/opscode-cookbooks/database#resourcesproviders:tilte


最終的なVagrantfileは以下の通りとなりました。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.hostname = "hoge"
  config.vm.box = "ubuntu120403"
  config.vm.network :private_network, ip: "33.33.33.10"
  config.vm.network :forwarded_port, guest: 3000, host: 9876

  config.berkshelf.enabled = true

  config.vm.provision :chef_solo do |chef|
    chef.json = {
      rbenv: {
        user_installs: [{
          user: "vagrant",
          rubies: ["1.9.3-p448"],
          global: "1.9.3-p448",
          gems: {
            "1.9.3-p448" => [
              {name: "bundler"}
            ]
          }
        }]
      },

      postgresql: {
        password: {
          postgres: "fuga"
        },

        dir: "/var/lib/postgresql/9.2/main",
        version: "9.2",
        enable_pgdg_apt: true,
        server: {
          packages: [
            "postgresql-9.2"
          ]
        },

        pg_hba: [
          { type: "host", db: "all", user: "all", addr: "127.0.0.1/32", method: "trust" }
        ],
      }
    }

    chef.run_list = [
        "apt",
        "git",
        "ruby_build",
        # See http://stackoverflow.com/questions/18616673/rbenv-vagrant-global-ruby-version-unchanged
        "rbenv::user",
        "postgresql::apt_pgdg_postgresql",
        "postgresql::server",
        "database::postgresql",
        "hoge::postgresql"     # 自作のレシピ
    ]
  end
end
recipes/postgresql.rb の作成

上記で自作のレシピ「hoge::postgresql」を指定したため、実際にそのレシピを追加します。内容はアプリのデータベース設定(ringo-tabetter/config/database.rb)に従います。
また、エンコードの設定方法はあったものの、LC_COLLATEとLC_CTYPEの設定方法が分からなかったため、エンコードのみの設定をしています。
なお、postgreユーザへの権限付与は不要でした。

postgresql_connection_info = {
    host:     'localhost',
    port:     5432,
    username: 'postgres',
    password: 'fuga'
}


# Create Database
postgresql_database 'herokudev' do
  connection postgresql_connection_info

  encoding 'utf8'
  action :create
end

Capistranoまわりの設定

Capfileの修正

今回のアプリがRuby1.9.3を指定しているため、「:rbenv_ruby」に「1.9.3-p448」を指定しておきます。



config/deploy.rbの修正

Padrinoの db:migrate と、「padrino start」時にホストOSからアクセスできるように「-h」を、デーモン化するために「-d」を、それぞれオプションに追加しています(必要に応じて「-p」によるポート指定も行います)。

set :application, 'my_app_name'

set :repo_url, 'https://github.com/thinkAmi/ringo-tabetter.git'
set :deploy_to, '/home/vagrant/ringo_tabetter'
set :scm, :git

namespace :deploy do

  desc 'Restart application'
  task :restart do
    on roles(:ringo) do
      within current_path do
        execute :rake, 'db:migrate'

        # seed内で画面入力が必要だったりするので、今回はコメントアウトしておく
        # execute :rake, 'db:seed'

        # 外部からアクセスできるように、 -h オプションを付ける
        # デーモン化するため、 -d オプションを付ける
        # 必要に応じて、 -p オプションでポートを指定しておく
        execute :bundle, :exec, 'padrino s -d -h 0.0.0.0'
      end
    end
  end

  after :restart, :clear_cache do
  end

  after :finishing, 'deploy:cleanup'

end

参考:

config/deploy/staging.rbの修正

今回はHerokuをproduction、Vagrant上をstagingとみなしたため、staging.rbを修正します。修正内容は以前と同様です。



実行

Vagrantの実行

d:\berkshelf\hoge>vagrant up

# 結果(抜粋)
[2013-11-20T21:32:35+00:00] INFO: Chef Run complete in 737.597979421 seconds


Capistranoの実行

d:\capistrano\fuga>bundle exec cap staging deploy

# 結果(抜粋)
 [34mINFO[0m [[32mead3026d[0m] Finished in 0.042 seconds with exit status 0([1m[32msuccessful[0m[0m).

結果の確認

vagrant ssh でゲストOSに入り、各種確認を行います。

d:\berkshelf\hoge>vagrant ssh
Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.0-29-generic i686)


Padrinoが使う、ポート3000が開いていることを確認します。

vagrant@hoge:~$ netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 0.0.0.0:33419           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:53            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN


psqlツールにて、DBのマイグレーションが行われているかを確認します。
なお、以下の記載に従い、UNIXアカウントのpostgresはロックしたまま、psqlツールを使います。
postgresql - What's the default superuser username/password for postgres after a new install? - Server Fault

vagrant@hoge:~$ sudo -u postgres psql postgres
psql (9.2.5)
Type "help" for help.


なお、psqlツールのコマンドの一覧は以下にあります。




データベースの一覧を確認します。アプリの設定通り、「herokudev」が存在していることを確認します。

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 herokudev | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
    +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres
    +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)


herokudevのテーブル一覧を表示し、必要なテーブルが存在していることを確認します。

postgres-# \c herokudev
You are now connected to database "herokudev" as user "postgres".


herokudev=# \dt
               List of relations
 Schema |       Name        | Type  |  Owner
--------+-------------------+-------+----------
 public | accounts          | table | postgres
 public | apples            | table | postgres
 public | schema_migrations | table | postgres
 public | tweets            | table | postgres
(4 rows)


最後のマイグレーション(ringo-tabetter/db/migrate/007_change_column_to_tweets.rb)より、「last_searched_id」列がbigintになっていることを確認します。

herokudev-# \d tweets
                                        Table "public.tweets"
      Column      |            Type             |                      Modifiers
------------------+-----------------------------+----------------------------------------------------
 id               | integer                     | not null default nextval('tweets_id_seq'::regclass)
 last_searched_id | bigint                      |
 created_at       | timestamp without time zone | not null
 updated_at       | timestamp without time zone | not null
Indexes:
    "tweets_pkey" PRIMARY KEY, btree (id)


あとは、ホストOSから、 localhost:9876 にアクセスし、Padrinoが起動していることを確認して、完了です。

*1:しばらくそのことに気づかず、ハマっていました

Windows7で Capistrano 3を使って、Vagrant上のUbuntuのrbenvにSinatraアプリをデプロイしてみた

前回、Berkshelf + Vagrantを使ってゲストOS上にrbenv環境を構築できたため、今回はその環境へ Capistrano 3 を使ってSinatraアプリをデプロイできないか試してみました。
なお、Capistranoは今年の6月にv3がリリースされたばかりのようで、Web上でよく目にするv2の設定情報とは異なっていたため、いろいろと悩みました。

環境

ホストOS
ゲストOS

流れ

Capistrano用の作業フォルダを作成・移動

d:\>mkdir capistrano\fuga
d:\>cd capistrano\fuga

デプロイ用のGemfileを作成

d:\capistrano\fuga>bundle init
Writing new Gemfile to d:/capistrano/fuga/Gemfile

Gemfileに記述

デプロイ先で Bundlerとrbenvを使うため、記載しておきます。

# A sample Gemfile
source "https://rubygems.org"

gem 'capistrano', "~>3.0.0"
gem 'capistrano-bundler', github: "capistrano/bundler"
gem 'capistrano-rbenv', github: "capistrano/rbenv"
Bundlerでインストール

d:\capistrano\fuga>bundle install
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.
Post-install message from capistrano:
If you're updating Capistrano from 2.x.x, we recommend you to read the upgrade g
uide: http://www.capistranorb.com/documentation/upgrading/

Capistrano用のセットアップ

d:\capistrano\fuga>bundle exec cap install
mkdir -p config/deploy
create config/deploy.rb
create config/deploy/staging.rb
create config/deploy/production.rb
mkdir -p lib/capistrano/tasks
Capified

Capfileの記述を修正・追加
set :rbenv_custom_path, '/home/vagrant/.rbenv'
set :rbenv_ruby, '2.0.0-p247'
deploy.rbファイル(fuga\config\deploy.rb)の修正

repo_urlを、SinatraアプリのGitHubリポジトリに変更

set :repo_url, 'https://github.com/thinkAmi/sinatra-hello-world.git'


デプロイ先の変更

set :deploy_to, '/home/vagrant/fuga'


scmでコメントアウトしてある以下のものをアンコメント

set :scm, :git
デプロイ先環境の設定

今回はゲストOSをproduction環境と考え、「d:\capistrano\fuga\config\deploy\production.rb」に以下の記述をしておきます。
なお、WindowsではVagrant用の鍵が環境変数「USERPROFILE」の下にあることから、設定ファイル内でその環境変数を展開して使用するため、「win32/registry」ライブラリをrequireしておきます。

require 'win32/registry'
key_path = Win32::Registry.expand_environ('%USERPROFILE%\.vagrant.d\insecure_private_key')

server '127.0.0.1', roles: %w{sinatra}, user: 'vagrant', port: 2222, ssh_options: {
  user: 'vagrant',
  keys: key_path,
  auth_methods: %w(publickey)
}

参考: Windowsの環境変数を含んだ文字列の展開 - DEAD BEEF



Vagrantfileの修正

Sinatraの動作確認をすることから、Vagrantでホストの適当なポート(今回は9876)をゲストのポート4567へフォワードするよう記述を追加します。

config.vm.network :forwarded_port, guest: 4567, host: 9876


Vagrantで起動している場合には、以下で再起動しておきます。

vagrant reload
Capistranoを使ったデプロイ

d:\capistrano\fuga>bundle exec cap production deploy

# 結果
[34mINFO[0m [[32m9aee9e3d[0m] Finished in 0.040 seconds with exit status 0([1m[32msuccessful[0m[0m).

sshによる確認

ゲストOSに vagrant ssh で入り、Sinatraを起動後、ホストOSのブラウザで動作を確認します。

d:\berkshelf\hoge>vagrant ssh
Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.0-29-generic i686)


vagrant@hoge:~$ cd fuga/current
vagrant@hoge:~/fuga/current$ bundle exec ruby app.rb -e production
[2013-11-12 21:39:37] INFO WEBrick 1.3.1
[2013-11-12 21:39:37] INFO ruby 2.0.0 (2013-06-27) [i686-linux]
== Sinatra/1.4.4 has taken the stage on 4567 for production with backup from WEBrick
[2013-11-12 21:39:37] INFO WEBrick::HTTPServer#start: pid=3472 port=4567
10.0.2.2 - - [12/Nov/2013 21:40:00] "GET / HTTP/1.1" 200 119 0.0108
10.0.2.2 - - [12/Nov/2013:21:40:00 UTC] "GET / HTTP/1.1" 200 119- -> /

参考: Sinatraがデフォルトでは外部から繋がらなくなってたよ - Qiita



問題なく動作しているようです。



補足

試しに、Sinatraの起動もCapistranoでやってみようと考え、deploy.rbに以下の記述を追加してみます。
executeについては、上の記述でも動作しましたが、短い下の方を使いました。

on roles(:sinatra) do
  within current_path do
    # execute :bundle, :exec, :ruby, "app.rb -e production"
    execute :ruby, 'app.rb -e production'
  end
end


その後、再度Capistranoでデプロイをします。

d:\capistrano\fuga>bundle exec cap production deploy


以下のログが出たところで、コマンドプロンプトの動作が停止していますが、実際にはゲストOSではSinatraが上がって動作しているようです。ホストOSのブラウザで確認したところ、正しく表示されコマンドプロンプトにもログが追加されました。

[0m[30mDEBUG[0m [[32mc117a5d5[0m] [31m [2013-11-12 20:33:19] INFO WEBrick::HTTPServer#start: pid=3072 port=4567
[0m


ただ、Capistranoから制御が戻らないのは問題なため、他の方法でSinatraを起動したほうが良さそうです(Ctrl + C でCapistranoの実行をキャンセルした場合、VM上のSinatraは動作したままでした)。



設定ファイル

補足部分も含め、以下の通りです。

Windows7でBerkshelf + Vagrantを使って、Ubuntu12.04.3に rbenv + Ruby + Padrino/Ruboto を入れてみた

Chefのcookbookを管理するツール「Berkshelf」が良さそうだったため、Windowsで試してみた時のメモ。

環境

ホストOS
ゲストOS
  • 前回の記事で作ったveeweeのBoxを元にVagrantで作成
  • rbenv + Rubyで 1.9系 と 2.0系 の設定を行う。
    • 2.0.0-p247 + Bundler + Padrino
    • 1.9.3-p448 + Bundler + Ruboto

事前準備

前回作ったBoxをVagrantにadd

忘れないようにaddしておきます。

d:\veewee\veewee>vagrant box add ubuntu120403 ubuntu120403.box
Downloading or copying the box...
Extracting box...ate: 336M/s, Estimated time remaining: --:--:--)
Successfully added box 'ubuntu120403' with provider 'virtualbox'!

流れ

今回使う、Berkshelf用のフォルダを作成・移動

d:\>mkdir berkshelf
d:\>cd berkshelf

Berkshelfのインストール

d:\berkshelf>gem install berkshelf --no-ri --no-rdoc

# 略
Successfully installed berkshelf-2.0.10
25 gems installed

BerkshelfのVagrantプラグインをインストール

VagrantとBerkshelfを連携させるために追加します。

d:\berkshelf>vagrant plugin install vagrant-berkshelf
Installing the 'vagrant-berkshelf' plugin. This can take a few minutes...
Installed the plugin 'vagrant-berkshelf (1.3.4)'!

ゲストOSのChefを最新版にするためのVagrantプラグインをインストール

念のために入れておきます。

d:\berkshelf>vagrant plugin install vagrant-omnibus
Installing the 'vagrant-omnibus' plugin. This can take a few minutes...
Installed the plugin 'vagrant-omnibus (1.1.2)'!

初期化

今回はhogeという環境を作ります。

d:\berkshelf>berks cookbook hoge
create hoge/files/default
create hoge/templates/default
create hoge/attributes
create hoge/definitions
create hoge/libraries
create hoge/providers
create hoge/recipes
create hoge/resources
create hoge/recipes/default.rb
create hoge/metadata.rb
create hoge/LICENSE
create hoge/README.md
create hoge/Berksfile
create hoge/Thorfile
create hoge/chefignore
create hoge/.gitignore
run git init from "./hoge"
create hoge/Gemfile
create hoge/Vagrantfile

Berksfileの修正

Berksfileに必要な各種cookbookを記載します。

site :opscode

metadata

cookbook 'apt'
cookbook 'git'
cookbook 'ruby_build'
cookbook 'rbenv', github: "fnichol/chef-rbenv"

Vagrantfileの修正

chef-rbenvのREADME.mdではnode.defalutで指定していますが、Vagrantで使うため、chef.jsonのところに直接記載します。


なお、Vagrant内のChefにて、rbenvでglobalのRubyバージョンを指定する方法は、以下を参考にしました。
chef - Rbenv vagrant global ruby version unchanged - Stack Overflow


また、実際の「Berksfile」と「Vagrantfile」は、Gistに置いておきました。
Berkshelf で rbenv + Ruby 環境を作成する時の Berksfile と Vagrantfile



Vagrantで起動

d:\berkshelf\hoge>vagrant up

できあがったゲストOSの環境を確認

Vagrant ssh」を使ってできあがった環境を確認します。rbenvの内容とデフォルトのRubyのバージョンは以下のとおりです。

d:\berkshelf\hoge>vagrant ssh
Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.0-29-generic i686)


vagrant@hoge:~$ rbenv versions
 system
 1.9.3-p448
* 2.0.0-p247 (set by /home/vagrant/.rbenv/version)


vagrant@hoge:~$ ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [i686-linux]


Ruby 2.0系環境にインストールされているgemの確認

vagrant@hoge:~$ gem list

*** LOCAL GEMS ***

activesupport (3.2.15)
bigdecimal (1.2.0)
bundler (1.3.5)
http_router (0.11.0)
i18n (0.6.5)
io-console (0.4.2)
json (1.7.7)
mail (2.5.4)
mime-types (1.25)
minitest (4.3.2)
multi_json (1.8.2)
padrino (0.11.4)
padrino-admin (0.11.4)
padrino-cache (0.11.4)
padrino-core (0.11.4)
padrino-gen (0.11.4)
padrino-helpers (0.11.4)
padrino-mailer (0.11.4)
polyglot (0.3.3)
psych (2.0.0)
rack (1.5.2)
rack-protection (1.5.1)
rake (0.9.6)
rdoc (4.0.0)
sinatra (1.4.4)
test-unit (2.0.0.0)
thor (0.17.0)
tilt (1.4.1)
treetop (1.4.15)
url_mount (0.2.1)


環境を切り替えて、Ruby 1.9系環境にインストールされているgemの確認

vagrant@hoge:~$ rbenv global 1.9.3-p448
vagrant@hoge:~$ gem list

*** LOCAL GEMS ***

arrayfields (4.9.0)
bigdecimal (1.1.0)
bundler (1.3.5)
chronic (0.10.2)
fattr (2.2.1)
io-console (0.3)
json (1.5.5)
main (5.2.0)
map (6.5.1)
minitest (2.5.1)
rake (0.9.2.2)
rdoc (3.9.5)
ruboto (0.15.0)

以上より、ゲストOSにセットアップできていることが確認できました。



その他

Vagrantの詳細なログを残すには、環境変数をセットした後、リダイレクトでログファイルなどに出力しておきます。

d:\berkshelf\hoge>set VAGRANT_LOG=debug
d:\berkshelf\hoge>vagrant up >> log.txt 2>&1

Windows7で、veeweeを使ってUbuntu12.04.3-DesktopのBoxを作る

以前Vagrantを利用したときは公開されているBoxを使用しましたが、自分でもBoxを作ってみようと考え、veeweeとそのテンプレートを使ってBoxを作ってみました。
Windowsでの構築については他にもいろいろとエントリがありますが、自分用のメモとして残しておきます。

 

環境


 
なお、利用するUbuntuのisoイメージはveeweeのテンプレートにあるdefinition.rb内で「:iso_file」として指定されているものと同じファイル名にした方が良いのかなと考え、以下の「PC (Intel x86) alternate install CD」(ファイル名:ubuntu-12.04.3-alternate-i386.iso)を事前にダウンロードしておきます。事前ダウンロードする理由は後述します。
Ubuntu 12.04.5 LTS (Precise Pangolin)

 

流れ

veeweeのインストール

今回はDドライブの直下にveeweeフォルダを用意して、その中にGitHubから持ってきたveeweeを入れます。

d:\>mkdir veewee


d:\>cd veewee


d:\veewee>git clone https://github.com/jedi4ever/veewee.git
Cloning into 'veewee'...
remote: Counting objects: 13219, done.
remote: Compressing objects: 100% (5085/5085), done.
Receiving objects: 100% (13219/13219), 3.86 MiB | 147 KiB/s, done.
emote: Total 13219 (delta 8735), reused 12256 (delta 7933)Resolving deltas: 0% (0/8735)
Resolving deltas: 100% (8735/8735), done.


d:\veewee>cd veewee


d:\veewee\veewee>bundle install
〜略〜
Using veewee (0.3.8.dev) from source at d:/veewee/veewee
Your bundle is complete!
Gems in the group kvm were not installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.

 

Boxの定義

今回はUbuntu12.04.3のデスクトップ版(32bit)を使用するため、veeweeのテンプレートを元に define します。

d:\veewee\veewee>bundle exec veewee vbox define ubuntu120403 'ubuntu-12.04.3-desktop-i386'


# 結果
The basebox 'ubuntu120403' has been successfully created from the template 'ubuntu-12.04.3-desktop-i386'
You can now edit the definition files stored in d:/veewee/veewee/definitions/ubuntu120403 or build the box with:
veewee vbox build 'ubuntu120403' --workdir=d:/veewee/veewee

 

isoフォルダを作り、インストール用isoファイルを入れる

veeweeでBoxを作る時に色々と試行錯誤するため、事前にダウンロードしておいた「ubuntu-12.04.3-alternate-i386.iso」ファイルをisoフォルダへ入れておき、veeweeでBoxをbuildするたびにインターネット経由でダウンロードすることを防ぎます。

d:\veewee\veewee>mkdir iso


 

各種設定ファイルの編集

まず、veeweeのdefinition.rb(D:\veewee\veewee\definitions\ubuntu120403\ubuntu120403\definition.rb)を編集します。
いろいろな展開はpuppetではなくchefを使う予定なので、puppetのセットアップを省略するため、41行目をコメントアウトしておきます。

#"puppet.sh",


次に、インストール用の設定ファイル(D:\veewee\veewee\definitions\ubuntu120403\preseed.cfg)を編集します。
今回はタイムゾーンを変更します(25行目あたり)。
他にも日本語キーボードレイアウトの設定などをしたかったのですが、現時点ではうまくいかなかったため、今回は諦めます。

# d-i time/zone string UTC
d-i time/zone string Asia/Tokyo

 

buildする

buildには時間がかかるため、しばらく放置します。

d:\veewee\veewee>bundle exec veewee vbox build ubuntu120403


# 結果
The box ubuntu120403 was built successfully!
You can now login to the box with:
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 7222 -l vagrant 127.0.0.1

 

Boxファイルとしてexportする

buildするとUbuntu仮想マシンが起動したままとなりますが、その状態で以下のコマンドを実行してエクスポートします(仮想マシンは自動的にシャットダウンします)。

d:\veewee\veewee>bundle exec veewee vbox export ubuntu120403


# 結果
Successfully exported 1 machine(s).
Packaging the box
Cleaning up temporary directory

To import it into vagrant type:
vagrant box add 'ubuntu120403' 'd:/veewee/veewee/ubuntu120403.box'

To use it:
vagrant init 'ubuntu120403'
vagrant up
vagrant ssh


以上で、Vagrant用のBoxが手に入りました。