アプリケーションデプロイの仕組み
いくつかの具体例で、クラウド上のPaaS環境にアプリケーションをデプロイした際の動作を説明します。
Rubyカートリッジ
まずは、単純に、ruby-1.9のギアを用意します。
# rhc app create -a rubyapp -t ruby-1.9 Password: ******** Creating application 'rubyapp' ============================== Cartridge: ruby-1.9 Gear Size: default Namespace: enakaidom Scaling: no (以下略)
この時、クライアント側にデフォルト構成のアプリケーションのコードが「git clone」でコピーされます。
# cd rubyapp/ # ll 合計 24 -rw-r--r--. 1 root root 3500 1月 5 16:14 2013 README -rwxr-xr-x. 1 root root 5588 1月 5 16:14 2013 config.ru drwxr-xr-x. 2 root root 4096 1月 5 16:14 2013 public -rw-r--r--. 1 root root 664 1月 5 16:14 2013 thread-dumper.rb drwxr-xr-x. 2 root root 4096 1月 5 16:14 2013 tmp
Rubyのカートリッジでは、ApacheのPassengerモジュールにより、Rack仕様のWebアプリケーションが実行されます。(それぞれのカートリッジの仕様は、OpenShift Originの各カートリッジのソースコードを見ると分かります。)Rackの説明は省略しますが、簡単に言うと、設定ファイルconfig.ruによって、呼び出し先のアプリケーションを切り替えることができます。
デフォルトでは、config.ruの中に、直接、HTMLが埋め込まれています。
config.ru
require 'rack/lobster' require './thread-dumper' map '/health' do health = proc do |env| [200, { "Content-Type" => "text/html" }, ["1"]] end run health end map '/lobster' do run Rack::Lobster.new end map '/' do welcome = proc do |env| [200, { "Content-Type" => "text/html" }, [<<WELCOME_CONTENTS <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <title>Welcome to OpenShift</title> <style> html { (以下略)
適当にコンテンツを編集したら、git commit/git pushを実行します。
# sed -i -e 's/Welcome to OpenShift/Hello, OpenShift!/' config.ru # git commit -a -m "New Title" # git push Counting objects: 5, done. Delta compression using up to 4 threads. Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 300 bytes, done. Total 3 (delta 2), reused 0 (delta 0) remote: restart_on_add=false remote: Waiting for stop to finish remote: Waiting for stop to finish remote: Waiting for stop to finish remote: Waiting for stop to finish remote: Done remote: restart_on_add=false remote: ~/git/rubyapp.git ~/git/rubyapp.git remote: ~/git/rubyapp.git remote: Running .openshift/action_hooks/pre_build remote: Running .openshift/action_hooks/build remote: Running .openshift/action_hooks/deploy remote: hot_deploy_added=false remote: Done remote: Running .openshift/action_hooks/post_deploy To ssh://369d22c1c9c94b5683c7f9c1e5652187@rubyapp-enakaidom.rhcloud.com/~/git/rubyapp.git/ bab6f7c..423cf72 master -> master
「git push」により、コンテンツがギアに送り込まれた後、ビルド処理が実施されます。ビルド処理の内容は、カートリッジによって異なります。JBossなどの場合は、mavenによるコンパイル処理が走ります。編集したコンテンツは、自動的にWebで公開されています。
実際にビルド処理を行う部分のソースは、こちらになります。ポイントは次の部分で、「Gemfile」が存在する場合は、ギア内部で、Bundlerによる依存モジュールのインストール処理が行われるようになっています。
if [ -f ${OPENSHIFT_REPO_DIR}/Gemfile ] then ... pushd ${OPENSHIFT_REPO_DIR} > /dev/null /usr/bin/scl enable ruby193 "bundle install --deployment" popd > /dev/null export GIT_DIR=$SAVED_GIT_DIR ... pushd ${OPENSHIFT_REPO_DIR} > /dev/null /usr/bin/scl enable ruby193 "bundle exec rake assets:precompile" 2>/dev/null popd > /dev/null
これを利用することで、Ruby on Railsなどのフレームワークを後から追加することが可能になります。具体例は次のセクションで。。。
Rubyカートリッジ + Ruby on Rails
まず、クライアント側にRailsとBundlerを導入しておきます。
# yum groupinstall "Development Tools" # yum install ruby-devel sqlite-devel postgresql-devel # gem install rails bundler
続いて、Ruby環境のギアを用意して、PostgreSQLカートリッジを追加します。
# rhc app create -a railsapp -t ruby-1.9 Password: ******** ... # rhc cartridge add postgresql-8.4 -a railsapp Password: ******** Adding 'postgresql-8.4' to application 'railsapp' Success postgresql-8.4 ============== Properties ========== Database Name = railsapp Connection URL = postgresql://127.7.164.129:5432/ Password = GjQxS4CsQcFT Username = admin
PostgreSQLのカートリッジを追加すると、DBの接続URLやパスワードなどが表示されます。これらは、ギア内部では、環境変数を通してアクセスできるので、特に覚えておく必要はありません。(とはいえ、トラブル対応用に記録しておくことはお勧めします。)
この例では、「railsapp」ディレクトリ以下にデフォルトのコンテンツが用意されていますが、これに被せる形で、Railsアプリケーションを作成します。
# ll 合計 12 drwxr-xr-x. 16 root root 4096 1月 5 16:04 2013 railsapp # rails new railsapp exist create README.rdoc create Rakefile conflict config.ru Overwrite /root/work/railsapp/config.ru? (enter "h" for help) [Ynaqdh] Y ...
必要なライブラリを追加しておきます。同じライブラリをギア上にも導入するため、必ず、Bundlerを利用して追加してください。
# cd railsapp # cat <<EOF >>Gemfile gem 'pg' gem 'execjs' gem 'therubyracer', '~> 0.10.2' EOF # bundle install
config/database.ymlにPostgreSQL接続情報を記載します。ここで、先に触れた、DB接続情報の環境変数を利用しています。
config/database.yml
production: adapter: postgresql encoding: utf8 database: <%=ENV['OPENSHIFT_APP_NAME']%> pool: 5 host: <%=ENV['OPENSHIFT_POSTGRESQL_DB_HOST']%> port: <%=ENV['OPENSHIFT_POSTGRESQL_DB_PORT']%> username: <%=ENV['OPENSHIFT_POSTGRESQL_DB_USERNAME']%> password: <%=ENV['OPENSHIFT_POSTGRESQL_DB_PASSWORD']%>
最後にもう1つだけ、仕込みがあります。新しいコードをgit pushした際に、ギア側で、DBのMigrate処理を実行させるためのものです。
# cat <<'EOF' >>.openshift/action_hooks/deploy pushd ${OPENSHIFT_REPO_DIR} > /dev/null bundle exec rake db:migrate RAILS_ENV="production" popd > /dev/null EOF
「.openshift/action_hooks」以下に用意されているスクリプトは、ギア側のさまざまな処理にフックして、任意の処理を実施するために利用します。ここでは、デプロイ処理後にMigrate処理を実施させています。
以上で準備は完了です。あとは、Railsアプリを作成して、git commit/git pushすればOKです。ここでは、ありがちなBlogアプリを用意してみます。
# rm public/index.html # rails generate controller home index # rails generate scaffold Post name:string title:string content:text # echo '<%= link_to "My Blog", posts_path %>' >> app/views/home/index.html.erb # git add . # git commit -a -m "Initial Application" # git push
「git push」の後、ギア側で、bundle installが走るので、追加ライブラリのインストール完了までに結構な時間がかかります。気長にお待ちください。無事にデプロイが完了すると、Webからアプリケーションが利用可能になります。
晒すほどのものではありませんが、一応、スクリーンショットを載せておきます。
次回は、Jenkinsカートリッジの使い方を書いておく予定です。。。。