ラベル heroku の投稿を表示しています。 すべての投稿を表示
ラベル heroku の投稿を表示しています。 すべての投稿を表示

2014年3月13日木曜日

[heroku][yesod] Heroku上でSQLiteを使ってはいけない

HerokuでSQLiteを使ってはいけない理由

なぜHerokuでSQLiteを使ってはいけないか。理由は以下の2つです。
  • HerokuのCedar Stackはephemeral filesystemを持っており、一見ファイルの読み書きができるように見えるが、一日に一度すべてクリアされる。このためSQLiteで保存したデータも毎日失われてしまう。
  • もしHerokuのファイルシステムが永続的にデータを保持したとしても別の問題がある。SQLiteはサービス機能を持っていないため各dynoの間でデータを共有することができず、それぞれ固有のDBを保持しているように振る舞ってしまう。
HerokuサイトのLearning - Application Architectureで公開されているSQLite on Herokuに詳細が説明されています。SQLiteの代わりにアドオンで提供されているPostgreSQL、MySQL、MongoDBなどを使うことになります。
今回YesodチュートリアルのYosogアプリで利用するデータベースをSQLiteからPostgreSQLに移行しました。その手順を紹介しておきます。

ローカル(mac)環境でのPostgres対応

まずローカル環境で動作しないことにはサーバ上で動作するはずがない、ということで、mac上のDevelopment環境でPostgreSQLを利用する手順を記載しておきます。
Yesodチュートリアルのサンプル(Yosogアプリ)をローカル環境でPostgreSQL上で動作させるには以下の修正が必要でした。yesod initコマンド実行時に利用DBとしてsqliteでなくpostgresqlを選択すれば、ここで述べるのSQLiteからPostgreSQLへの変更手順は不要になります。
  1. SQLite環境をPostgreSQL環境に変更
    1. Application.hsのdbconfをSQLiteからPostgreSQLに
    2. 
      -     dbconf <- withYamlEnvironment "config/sqlite.yml" (appEnv conf)
      +     dbconf <- withYamlEnvironment "config/postgresql.yml" (appEnv conf)
      
      
    3. Settings.hsのPersistentConfをSQLiteからPostgreSQLに
    4. (その1)
      
      -import Database.Persist.Sqlite (SqliteConf)
      +import Database.Persist.Postgresql (PostgresConf)
      
      
      (その2)
      
      -type PersistConf = SqliteConf
      +type PersistConf = PostgresConf
      
      
    5. Yosog.cabalのbuild-dependsをpersistent-sqliteからpersistent-postgresに
    6. (その1)
      
      -                 , persistent-sqlite             >= 1.3        && < 1.4
      +                 , persistent-postgresql         >= 1.3        && < 1.4
      
      
      (その2)
      
      -                 , persistent-sqlite
      +                 , persistent-postgresql
      
      
    7. config/postgresql.ymlの準備
    8. 
      Default: &defaults
        user: Yosog
        password: Yosog
        host: localhost
        port: 5432
        database: Yosog
        poolsize: 10
      
      Development:
        <<: *defaults
      
      Testing:
        database: Yosog_test
        <<: *defaults
      
      Staging:
        database: Yosog_staging
        poolsize: 100
        <<: *defaults
      
      Production:
        database: Yosog_production
        poolsize: 100
        <<: *defaults
      
      
  2. MacPortsでpostgresql93をインストールする
    1. postgresql93パッケージをインストール
    2. 
      % sudo port install postgresql93
      % sudo port install postgresql93-server
      % sudo port select postgresql postgresql93
      
      
    3. DBインスタンスの生成(serverのinstall時の指示に従う)
    4. 
      % sudo mkdir -p /opt/local/var/db/postgresql93/defaultdb
      % sudo chown postgres:postgres /opt/local/var/db/postgresql93/defaultdb
      % sudo su postgres -c '/opt/local/lib/postgresql93/bin/initdb -D /opt/local/var/db/postgresql93/defaultdb' 
      
      
    5. サーバーの起動
    6. 
      % sudo launchctl load -w /Library/LaunchDaemons/org.macports.postgresql93-server.plist
      % sudo launchctl start org.macports.postgresql93-server
      
      

  3. Yosogアプリが利用するDBを生成する
    1. ユーザーとデータベースの生成
    2. 自動生成されるconfig/postgres.ymlを確認するとYosogユーザーでYosogデータベースにアクセスする設定になっています。このため以下のコマンドでユーザーとデータベースを作成しておきます。
      
      % createuser -U postgres -P Yosog
      % createdb -U postgres Yosog
      
      
      ユーザーとデータベースが作成されていないと、Yosogアプリ起動時に以下のエラーになります。
      
      Yosog: SqlError {sqlState = "", sqlExecStatus = FatalError, sqlErrorMsg = "FATAL:  role \"Yosog\" does not exist\n", sqlErrorDetail = "", sqlErrorHint = ""}
      
      
    3. PostgreSQL対応したYosogアプリの起動
    4. 
      % cabal run -- Development
      
      

HerokuにPostgreSQL対応版Haskell/Yesodアプリをdeployする

PostgreSQLを利用する手順はRuby on Rails上であればHerokuのドキュメントで紹介されています。ここではHaskellのYesodフレームワーク上でPostgreSQLを利用するサーバーをHerokuにデプロイするための手順を示しておきます。
  1. postgresqlアドオンの登録&接続情報の確認
    1. postgresqlアドオン登録
    2. 
      %  heroku addons:add heroku-postgresql:dev
      
      
    3. DB情報の確認
    4. 
      % heroku pg:info
      === HEROKU_POSTGRESQL_IVORY_URL
      Plan:        Dev
      Status:      available
      Connections: 0
      PG Version:  9.3.3
      Created:     2014-03-12 15:42 UTC
      Data Size:   6.4 MB
      Tables:      0
      Rows:        0/10000 (In compliance)
      Fork/Follow: Unsupported
      Rollback:    Unsupported
      
      
    5. 接続情報の確認
    6. 
      % heroku pg:credentials HEROKU_POSTGRESQL_IVORY_URL
      Connection info string:
         "dbname=ddddd host=aaa-11-222-33-44.compute-1.amazonaws.com port=5432 user=uuuuu password=XXXXX sslmode=require"
      Connection URL:
          postgres://uuuuu:XXXXX@aaa-11-222-33-44.compute-1.amazonaws.com:5432/ddddd
      
      
  2. 接続情報の反映と接続確認
    1. config/postgresql.ymlの編集
    2. 接続情報で確認した、dbname, host, user, passwordをpostgresql.ymlのProduction:の設定に反映します。
      
      --- a/config/postgresql.yml
      +++ b/config/postgresql.yml
      @@ -19,6 +19,10 @@ Staging:
         <<: *defaults
       
       Production:
      -  database: Yosog_production
      +  user: uuuuu
      +  password: XXXXX
      +  host: aaa-11-222-33-44.compute-1.amazonaws.com
      +  port: 5432
      +  database: ddddd
         poolsize: 100
         << *defaults
      
      
    3. postgresql対応版サーバーのdeploy
    4. 
      % git commit -m "- use postgersql instead of sqlite." .
      % git push heroku master
      % heroku open
      
      
    5. psqlを用いた接続確認(おまけ)
    6. 以下のコマンドでPCからadonしたPostgreSQLのDBに接続することができます。postgresql.ymlのDevelopment:欄に同様の設定をすればアプリ本体はPC上、DBはサーバー上の組み合わせで動作確認することもできます。
      
      % psql -h aaa-11-222-33-44.compute-1.amazonaws.com -p 5432 -U uuuuu DDDDD
      ddddd> \d
                        List of relations
       Schema |      Name      |   Type   |     Owner      
      --------+----------------+----------+----------------
       public | article        | table    | uuuuu
       public | article_id_seq | sequence | uuuuu
       public | email          | table    | uuuuu
       public | email_id_seq   | sequence | uuuuu
       public | user           | table    | uuuuu
       public | user_id_seq    | sequence | uuuuu
      (6 rows)
      
      

ここまでの修正はGitHubにコミット済みです。
https://github.com/kurokawh/Yosog/tree/Yosog_PostgreSQL
メモ:ローカルリポジトリの変更をリモートのmaster以外の別ブランチにプッシュするには、以下のコマンドを実行する。

% git push origin master:Yosog_PostgreSQL
Counting objects: 24, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (18/18), done.
Writing objects: 100% (18/18), 2.02 KiB | 0 bytes/s, done.
Total 18 (delta 12), reused 0 (delta 0)
To https://kurokawh@github.com/kurokawh/Yosog.git
   be68e29..8a25b29  master -> Yosog_PostgreSQL
% git branch -r
  origin/Yosog_PostgreSQL
  origin/master


参考にした情報:

2014年3月3日月曜日

[heroku][yesod] YesodアプリをHeroku上にデプロイする手順

YesodアプリをHeroku上にデプロイできました!以前にローカル環境で確認したYesodチュートリアルのwebアプリケーションをHeroku上で動作させることができたので、その手順をまとめておきます。

前提環境:

  • Yesodチュートリアルのアプリケーション(Yesog)が動作している
  • gitがインストールされている
  • heroku toolbeltがインストールされている
  • 動作確認した環境の詳細
    • % ghc --version
      • The Glorious Glasgow Haskell Compilation System, version 7.6.3
    • % cabal --version
      • cabal-install version 1.18.0.2
      • using version 1.18.1.2 of the Cabal library 
    • % yesod version
      • yesod-bin version: 1.2.6
    • % heroku version
      • heroku-toolbelt/3.4.1 (x86_64-darwin10.8.0) ruby/1.9.3

デプロイ手順:

以下の手順を実行することでYosogアプリケーションをHeroku上にデプロイし、クライアントからアクセスできるようになります。
  1. Yosog.cabalをエディタで開き、以下の取り消し線部分の記述を削除する
  2. 
    
    executable         Yosog
    
        if flag(library-only)
            Buildable: False
    
        main-is:           main.hs
        hs-source-dirs:    app
        build-depends:     base
                         , Yosog
                         , yesod
    
    
    この記述があると、cabal runで以下のようなエラーが発生してしまいます。原因不明…。
    
    cabal: Cannot build the executable 'Yosog' because the component is marked as
    
    disabled in the .cabal file.
    
    
  3. YosogルートディレクトリにProfileを用意する
  4. 
    % echo "web: cabal run -- production -p $PORT" > Profile
    
    
    このファイルはHerokuがサーバーを起動する手順になります。ローカル環境でも同様のコマンドでサーバーが起動することを確認しておきましょう。
  5. gitリポジトリにファイルを登録
  6. 
    % git init .
    % git add *
    % git commit -m "Initial commit." .
    
    
  7. heroku上にアプリケーションを登録
  8. 
    % heroku create --stack=cedar --buildpack https://github.com/begriffs/heroku-buildpack-ghc.git
    
    
  9. heroku上にアプリケーションをデプロイ
  10. 
    % git push heroku master
    
    
    10分くらい時間がかかります。状況によっては15分のビルド時間制限をオーバーしてしまうこともあるようです。そのようなときには、以下の手順で別サーバーでビルドを実行することができる模様。
    
    % heroku plugins:install https://github.com/ddollar/heroku-anvil
    % heroku build -r -b https://github.com/begriffs/heroku-buildpack-ghc.git
    
以上です。
heroku open
上記のコマンドでパブリックなサーバーとして起動しているYosogアプリケーションにアクセスすることができます。GitHubでこの環境をを公開しておきます。

  • https://github.com/kurokawh/Yosog.git
  • 参考情報:

    以下、参考にした情報についてまとめておきます。複数サイトの情報を参照しつつ作業したのですが、自分の環境ではうまくいかなかった手順もありました。最終的に最も成功に近かった手順は以下のサイトの情報になります。
    以下のサイトの情報も試しましたが、いずれもクライアントからアクセスできる状態にたどりつけませんでした。
    • Haskell Buildpack Demo
      • サンプルのデプロイ、動作確認は成功。だが、自環境のYosogアプリについては、deployまで成功したが、heroku openを実行してもサーバーとは繋がらず…。
    • MacでHerokuにYesodを(Herokuに公開編)
      • この手順はバイナリをgitコミットして、コンパイルなしてサーバー上で起動する手順だと思われます。mac上でビルドしたバイナリはdeployまではできるものの、heroku openで繋がりませんでした。

    その他、新たに学習した情報のメモ

    いろいろはまったことで、自分にとっての新しい知識が少しだけ増えました。Herokuへのデプロイと直接は関係しませんが、それらもまとめておきます。
    • yesodアプリをリリースビルドする手順
      • scafoldsiteではyesod develでビルド&テストサーバーが起動されますが、リリース用のバイナリを生成するには
        • cabal install
      • を実行することになります。このコマンドを実行すると
        • dist/dist-sandbox-5ba8a016/build/Yosog/Yosog
      • が生成されます。production -p XXXという引数とともにこのバイナリを起動すると、プロダクション版のサーバーを起動できます。
        • dist/dist-sandbox-5ba8a016/build/Yosog/Yosog production -p 3000
    おわり。

    2014年2月2日日曜日

    [heroku] はじめてのheroku

    インターネット上の情報を参考にしながら、自分のMacにherokuを利用する上で最低限の環境を構築しrubyとHaskellのサンプルウェブアプリを動かしてみた。

    Mac上の準備:

    1. MacPortsをインストール(手順はここ
    2. portsでruby19をインストール(port install ruby19。こちらの手順で複数のバージョンを選択切り換えができます)
    3. heroku toolbeltをインストール(ここからインストーラをダウンロードして、インストール)
      • 以前はruby gemでherokuをインストールしていたようです(gem install heroku)

    ruby版サンプルサーバーのherokuへのデプロイ:

    
        % git clone git://github.com/heroku/ruby-sample.git
        % cd ruby-sample/
        % heroku create
        % git push heroku master
        % heroku open
    
    
    これだけで"Hello World!"が表示されるウェブアプリが動き始めた!ローカル環境にrailsもインストールしたのですが、heroku上でサーバーを動作させるだけであればrailsのインストールは不要でした。

     Haskell版サンプルサーバーのherokuへのデプロイ:

    ここの情報を参考にherokuのサンプルも動作した!
    
        % git clone https://github.com/pufuwozu/haskell-buildpack-demo.git
        % cd haskell-buildpack-demo/
        % heroku create --stack=cedar --buildpack https://github.com/pufuwozu/heroku-buildpack-haskell.git
        % git push heroku master
        % heroku open
    
    
    このサンプルではWarp(Haskell製ウェブサーバー)を直に利用している。 自分が利用しようとしているのはウェブアプリケーションフレームワークのYesod(内部でWarpを使用)なので、Heroku上でYesodを利用する方法は別途調査が必要。こちらにはsnap(yesodとは別のweb framework)のデプロイサンプルがある。
    Haskellのサーバーをheroku上で動作させる方法は、このサンプルのようにビルドパッケージを利用する方法以外に、あらかじめコンパイルしてgitリポジトリにコミットしたバイナリを動作させる方法もあるようなので、後者についても少し調べてみる予定。

    Yesodのチュートリアルサンプルのデプロイ:

    試しに、昨年末にローカルで動作を確認したYesodチュートリアルサンプルをheroku上にデプロイしようとしてみましたが…エラーになりました。orz
    
    % git push heroku master
    Initializing repository, done.
    Counting objects: 95, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (87/87), done.
    Writing objects: 100% (95/95), 78.89 KiB, done.
    Total 95 (delta 28), reused 0 (delta 0)
    
    -----> Fetching custom git buildpack... done
    -----> Haskell app detected
    -----> Downloading GHC
    ######################################################################## 100.0%
    -----> Downloading Cabal
    ######################################################################## 100.0%
    -----> Updating Cabal
    Downloading the latest package list from hackage.haskell.org
    Note: there is a new version of cabal-install available.
    To upgrade, run: cabal install cabal-install
    -----> Release the hounds! Installing application
    Resolving dependencies...
    cabal: Could not resolve dependencies:
    trying: Yosog-0.0.0
    trying: fast-logger-2.1.5
    rejecting: warp-2.0.2, 2.0.1, 2.0.0.1, 2.0.0 (conflict: Yosog => warp>=1.3 &&
    <1 .4="" conflict:="" rejecting:="" trying:="" wai-2.0.0="" warp-1.3.10.1="" warp=""> wai>=1.3 && <1 .5="" 2.0.0.1="" 2.0.0="" 2.0.1.1="" 2.0.1.2="" 2.0.1="" 2.0.2="" 2.0.3.1="" 2.0.3.2="" 2.0.3="" conflict:="" rejecting:="" trying:="" wai-1.4.1="" wai-extra-2.0.3.3="" yosog=""> wai-extra>=1.3 && <1 .4="" 1.3.2.4="" 1.3.3.1="" 1.3.3.2="" 1.3.3="" 1.3.4.1="" 1.3.4.2="" 1.3.4.3="" 1.3.4.4="" 1.3.4.5="" 1.3.4="" conflict:="" fast-logger="=2.1.5," rejecting:="" wai-extra-1.3.4.6="" wai-extra=""> fast-logger>=0.2 && <0 .4="" 1.3.0.1="" 1.3.0.2="" 1.3.0.3="" 1.3.0.4="" 1.3.0.5="" 1.3.0="" 1.3.1.1="" 1.3.1="" 1.3.2.1="" 1.3.2.2="" 1.3.2="" conflict:="" rejecting:="" wai-extra-1.3.2.3="" wai-extra="" wai="=1.4.1,"> wai>=1.3 && <1 .4="" 0.0.0.1="" 0.0.0.2="" 0.0.0="" 0.1.0="" 0.1.1="" 0.1.2.1="" 0.1.2="" 0.1.3.1="" 0.1.3="" 0.2.0="" 0.2.1="" 0.2.2.1="" 0.2.2.2="" 0.2.2="" 0.2.3="" 0.2.4.1="" 0.2.4.2="" 0.2.4="" 0.3.0="" 0.3.1="" 0.3.2.1="" 0.3.2="" 0.3.3="" 0.4.0.1="" 0.4.0.2="" 0.4.0.3="" 0.4.0="" 0.4.1.1="" 0.4.1.2="" 0.4.2="" 0.4.3="" 0.4.4="" 0.4.5.1="" 0.4.5.2="" 0.4.5="" 0.4.6="" 1.0.0.1="" 1.0.0="" 1.1.0.1="" 1.1.0="" 1.2.0.1="" 1.2.0.2="" 1.2.0.3="" 1.2.0.4="" 1.2.0.5="" 1.2.0="" conflict:="" rejecting:="" wai-extra-1.2.0.6="" yosog=""> wai-extra>=1.3 && <1 -="" .4="" app="" compile="" failed="" git="" haskell="" heroku.com:fierce-shore-6905.git="" master="" push="" rejected="" remote="" to=""> master (pre-receive hook declined)
    error: failed to push some refs to 'git@heroku.com:fierce-shore-6905.git'
    
    

    (3/2追記)
    上記のエラーは、ローカルでyesod init後にcabal installした際に、自分の環境の古い各種パッケージへの依存がYosog.cabalに記録され、Herokuで利用するビルドパック環境とあわないのが原因のようです。ローカルの環境をcabal updateで最新にして、cabal installした際に生成したYosog.cabalをコミットしてサーバーにデプロイしたところコンパイルは通るようになりました。
    ですが残念なことに、heroku openしてもサーバーにはつながらず…。原因調査中です。