Azure + Nginx + Capistrano でRailsアプリのデプロイ
以下のWindows Azure公式ドキュメントにやり方があったので、ここを参考に進めていく。
http://azure.microsoft.com/en-us/documentation/articles/virtual-machines-ruby-deploy-capistrano-host-nginx-unicorn/azure.microsoft.com
(heroku使いてぇ...)
VMつくる
Azureで仮想マシンを作成します。この前やったのと同じ要領でつくった。
Windows Azure + Rails でサーバーを構築してみる - 珈琲駆動開発
自動でデプロイできるようにするには鍵認証でssh接続できる必要があるらしいので、以下を見ながら.pemファイルを作成して、それを使う。
Use SSH to connect to Linux virtual machines in Azure
またENDPOINTSではHTTPを追加します
ということでここまでのインストールしたものとかをもう一度インストールしなおす。。シェルスクリプトでやってしまうべし
ログインは以下でいけます。
# ssh -i myPrivateKey.key -p <port> username@servicename.cloudapp.net
サーバーにもろもろインストール
sudo apt-get update sudo apt-get -y upgrade sudo apt-get -y install git build-essential libssl-dev curl nodejs nginx git clone git://github.com/sstephenson/rbenv.git ~/.rbenv echo 'export RBENV_ROOT=~/.rbenv' >> ~/.bash_profile echo 'export PATH="$RBENV_ROOT/bin:$PATH"' >> ~/.bash_profile echo 'eval "$(rbenv init -)"' >> ~/.bash_profile source ~/.bash_profile eval "$(rbenv init -)" git clone git://github.com/sstephenson/ruby-build.git cd ruby-build sudo ./install.sh ~/.rbenv/bin/rbenv install 2.0.0-p451 ~/.rbenv/bin/rbenv global 2.0.0-p451 gem install bundler ~/.rbenv/bin/rbenv rehash
rubyが入ってるか確認。
$ ruby -v ruby 2.0.0p451 (2014-02-24 revision 45167) [x86_64-linux]
PostgreSQLインストール
PostgreSQLインストールします
$ sudo apt-get -y install postgresql postgresql-contrib libpq-dev
以下でPostgreSQLのユーザ名を登録。したらDBを作るのだけど、これはユーザ名と同じにする。らしい。これはcapistranoでデプロイするときのルールとのこと。
一行目でパスワードの設定が求められる。
$ sudo -u postgres createuser -D -A -P my_username $ sudo -u postgres createdb -O my_username my_database
試しに接続してみる
$ psql -U my_username -W my_database
パスワードを入力して以下のように入力画面になればok
Password for user totz: psql (9.1.15) Type "help" for help. totz=>
Nginxのテスト
nginxを起動。
$ sudo service nginx start
以下のように表示されればおけ!
やったーー動いてるううう
今回初めてNginx使った(エンジンエックスと読む。なんか中2感あってかっこいい)。以下の記事が参考になる。
これから始める人のためのNginx(1):高速・軽量・高機能……Nginxの基礎知識 (1/2) - @IT
Raisアプリの修正
デプロイするため、Unicorn web server、PostgreSQL、Capistranoに対応するようRailsアプリを修正していきます。
Capistranoの使い方は以下が一番詳しそう。勉強勉強
入門 Capistrano 3 ~ 全ての手作業を生まれる前に消し去りたい | GREE Engineers' Blog
- Capistranoは2まではRailsのデプロイツールだったけど、3は汎用的なデプロイツールに変わっている。したがってデフォルトの状態ではRails用のデプロイタスクは特に含まれていない
まずGemfile
に以下を追加します。
# Use Unicorn gem 'unicorn' # Use PostgreSQL gem 'pg', group: :production group :development do # Use Capistrano for deployment gem 'capistrano', '~> 3.1' gem 'capistrano-rails', '~> 1.1.1' gem 'capistrano-bundler' gem 'capistrano-rbenv', '~> 2.0' gem 'capistrano-unicorn-nginx', '~> 2.0' gem 'capistrano-postgresql', '~> 3.0' end
インストール
$ bundle
ここでCapistranoとは。以下の記事を参考に。
CapistranoはRubyで記述されたデプロイメントツールで、SSH経由で複数のリモートマシン上で並列にコマンドを実行するためのフレームワークです。一般的には、git(github含む)やsubversion等といったSCM(Source Code Management)からソースコードをアプリケーションサーバへデプロイしたり、アプリケーション関連ディレクトリの管理やデータベースの更新等を行うことが多いと思います。
あとこことか
特集 DevOps時代の必須知識:まとめてたくさん処理したい! を解決する「Capistrano」 - @IT
$ cap install
で以下のようにファイルが作成されます
▶ 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 create Capfile Capified
おもにconfig
ディレクトリ内のファイルがcapistranoのデプロイ設定ファイルで、さらにその中のdeploy/production.rb
とdeploy/staging.rb
で詳しく設定できる。
ルートにあるCapfileの該当する場所(必要なもの)のコメントアウトを外す。
# Capfile # require 'capistrano/rvm' require 'capistrano/rbenv' # require 'capistrano/chruby' require 'capistrano/bundler' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' # require 'capistrano/passenger'
さらに以下を追加。
require 'capistrano/unicorn_nginx' require 'capistrano/postgresql'
そしてconfig/deploy.rb
を以下のように変更
lock '3.1.0' # application name and the github repository set :application, 'YourApplicationName' set :repo_url, 'git@github.com:YourGitHubName/YourRepoName.git' # describe the rbenv environment we are deploying into set :rbenv_type, :user set :rbenv_ruby, '2.0.0-p451' set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec" set :rbenv_map_bins, %w{rake gem bundle ruby rails} # dirs we want symlinked to the shared folder # during deployment set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system} namespace :deploy do desc 'Restart application' task :restart do on roles(:app), in: :sequence, wait: 5 do # Your restart mechanism here, for example: # execute :touch, release_path.join('tmp/restart.txt') # # The capistrano-unicorn-nginx gem handles all this # for this example end end after :publishing, :restart after :restart, :clear_cache do on roles(:web), in: :groups, limit: 3, wait: 10 do # Here we can do anything such as: # within release_path do # execute :rake, 'cache:clear' # end end end end
そして次はconfig/deploy/production.rb
を以下のように変更
# production deployment set :stage, :production # use the master branch of the repository set :branch, "master" # the user login on the remote server # used to connect and deploy set :deploy_user, "YourAzureVMUserName" # the 'full name' of the application set :full_app_name, "#{fetch(:application)}_#{fetch(:stage)}" # the server(s) to deploy to server 'YourVM.cloudapp.net', user: 'YourAzureVMUserName', roles: %w{web app db}, primary: true # the path to deploy to set :deploy_to, "/home/#{fetch(:deploy_user)}/apps/#{fetch(:full_app_name)}" # set to production for Rails set :rails_env, :production
サーバー上デプロイ用の設定を書いてる
そしたらgitリポジトリの内容をコミットして更新しておく。
デプロイ
ついについにデプロイ...!!
以下で実行。
▶ bundle exec cap production setup
なんかエラー出た。
cap aborted! SSHKit::Runner::ExecuteError: Exception while executing as totz@vm.cloudapp.net: Authentication failed for user totz@vm.cloudapp.net Net::SSH::AuthenticationFailed: Authentication failed for user totz@vm.cloudapp.net Tasks: TOP => rbenv:validate (See full trace by running task with --trace) 4m ⚑ ⍉
ssh接続するためのkeyを指定できてないからかな。
config/deploy/production.rb
のssh_optionsをいじったらいけた。ローカルのkeyを指定して、パスワードをいれたら、setupは通るようになってサーバー側にconfigファイルとかが生成されたけど、今度はdeployでエラーがでた。
SSHKit::Runner::ExecuteError: Exception while executing as totz@bodabodavm.cloudapp.net: git exit status: 128 git stdout: Nothing written git stderr: Warning: Permanently added 'github.com,192.30.252.129' (RSA) to the list of known hosts. Permission denied (publickey).
git側と鍵認証がうまくできてないようだ。。
以下あたりを参考にしながらローカル側でagent_forwardの設定して、鍵を生成してgithubに登録した。
Use SSH agent forwarding to deploy via Capistrano : grits – the blenderbox blog
Using SSH Agent Forwarding | GitHub API
ちなみに agent_forwardとは
ホストマシンのssh-agentをログイン先のマシンからも参照できるsshの機能です。 これを利用することで、githubなどいろいろなところに登録されたホストマシンの公開鍵を、ローカルVMからも利用することができ、開発の際に捗ります。
ssh-agentのforwardを利用し、ホストマシンとローカルVMの非公開鍵を共有する - MANA-DOT
というものらしく。VMを使って開発するときとか便利!!
そしてこのあともう一度deployコマンド叩いてみて、もう少し進むようになったけど、今度はrbenvのcommandがみつからないとか、、
どうやらbashでうまくrbenvにパスが通ってなかったらしい。~/.bash_profile
の設定をいちからやりなおしたらrbenvコマンドが叩けるようになったのでもういちどdeploy
今度は
DEBUG [3cc901e3] rbenv: bundle: command not found
なんて言われた。ということで以下でbundlerをインストール。
$ gem install bundler
$ rake db:migrat
がうまくいっていなかったようなのでgithubのcapistrano-postgresqlのREADMEをみてみると以下の記述が。
Be sure to remove config/database.yml from your application's version control.
capistrano-plugins/capistrano-postgresql · GitHub
なおらない。。
次はこちらの記事で。
さくらVPS Capistrano編 - プログラミングノート
サーバー上のdatabase.yml
のユーザ名とパスワードを修正。
migratingはいけた。。。!!!!
と思ったら次はnginxのエラー。エラーに続くエラーだよほんと。。
[67f25685] Reloading nginx configuration: DEBUG [67f25685] nginx: the configuration file /etc/nginx/nginx.conf syntax is ok DEBUG [67f25685] nginx: [emerg] open() "/home/bodaapivm/apps/boda_api_production/shared/log/nginx.access.log" failed (2: No such file or directory) DEBUG [67f25685] nginx: configuration file /etc/nginx/nginx.conf test failed
となってしまった。明らかに/homeの下のユーザのとこがおかしい。最初に書き間違えてたのがダメだったのか。
Reloading nginx configurationのタスクは以下の部分っぽい。
capistrano-unicorn-nginx/nginx.rake at master · capistrano-plugins/capistrano-unicorn-nginx · GitHub
ここのnginx_service_pathというのが怪しそう。。
いい方法が思いつかなかったのでVMをもう一度作り直した。(AzureはOSの再インストール的なのできないのかなー)
すると、、、デプロイできたー!!
けど画面には何も表示されない。とりあえず$ rake routes
でルーティングができているか確認してみると以下のようなメッセージが
ActiveRecord::AdapterNotSpecified: 'development' database is not configured. Available: ["production"]
ググったらここがでた。
参考にして、shared/config/database.yml
の情報を書き換える。ここがなんかAzureのdashboardで設定していたものと違っていた。
Railsのデプロイでハマった点まとめ - そのねこが学ぶとき
Qoosky - Rails4のデプロイでCapistrano3の基本的な使い方を把握する
ローカルのconfig/database.yml
は管理対象から外して、リモートではshared/
以下の設定ファイルを用いる。
この2つのフォルダをcurrent配下にシンボリックリンクすることにより、currentが実際のアプリ配置場所として機能する。
と思ったらリフレッシュしても今度は画面が真っ白。ググったら以下の記事が参考になりました。
Rails が production 環境で真っ白、SECRET_KEY_BASE 設定忘れが原因でした | EasyRamble
tailsコマンドなんてのがあるんだなー。-f
オプションはファイルの内容を常に監視し,表示を更新するもの。このコマンドすごく便利です。
unicornのreloadできなかったのでぐぐってみると以下の記事が。
ruby on rails 3 - Unicorn with Foreman - Socket Already Used Error - Stack Overflow
コメントアウトしてもうまくいかない。とりあえずローカルのconfig/deploy/production.rb
に以下を加えてunicornのreloadのタスクをcapistranoのタスクから外す。
Rake::Task["unicorn:restart"].clear_actions
どうやらunicornを再起動するときにプロセスをkillできてない(ID間違えっぽい?)みたいなのでsshでサーバにログインしてprocess idがあっているか確認してみる。
以下でunicorn関連のプロセスを確認する。
$ ps aux | grep unicorn
killするprocess idはshared/tmp/pids/unicorn.pid
によって決められているみたいなので、これをさっっき確認した走ってるprocess idに書き換える。
(でもこのprocess idはどういう基準で決められるんだろう...)
すると、動いたのは動いたけどリフレッシュすると2回に1回500 Internal server errorが返ってくる...。
なんかさっきの段階でゾンビなプロセスがたくさん走ってたようなので一回全部手動でkillしてもういちどunicornをloadしたら正常に動くようになった。
やっとやっと動きました...!!!!
ここまでなんか1週間弱かかった。なんなんだほんと...笑
とりあえずAzureとかnginxとかCapistranoを使って一通りRailsのデプロイを体験できたので、まぁよかったかなと。この苦しい期間でいろいろ学んだこともあったし。。。笑
勉強がんばろ!もっともっとコード書こう!!