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:しばらくそのことに気づかず、ハマっていました