capistrano エラー currentディレクトリが削除できません

EC2のインスタンスをAMIから複製して、本番環境つくってcapistrano3で本番環境へのデプロイをつくっております。
でもエラーになりました。currentを削除できませんということです。

権限がおかしかった。
参考:http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/install-LAMP.html

sudo chown -R root:www /var/www
sudo chmod 2775 /var/www
find /var/www -type d -exec sudo chmod 2775 {} +
find /var/www -type f -exec sudo chmod 0664 {} +

capistrano3でcakephpのmigrations pluginを実行させる

cookpadの人がridgepoleというのを作られまして、これはべきとうせいが保証されているらしい。ちなみにべきとうせいという読み方は間違っているかもしれない。漢字が変換で出てこない。どうもテーブル一覧つくってそれを更新するだけでいいっぽくて、その一覧をみながらないやつを足したり、いらないやつを削除したりしてくれるっぽい。migrations pluginみたいに、ここではaテーブルを追加し、次はbテーブルを削除しつつ、cテーブルを追加する、とかだと、もうaテーブルが既に存在する時点で終了になったりするのですごく便利な気がする。

といいつつ、今回はmigrations pluginをcapistranoで実行させます。サブモジュールがデプロイできない。下記の真似したらできた。自分は拡張子が.capで大丈夫だった。確かに拡張しはCapfileに書いてあった。

capistrano3 + git で submodule も一緒にデプロイしたい場合

上記にて、migrations pluginを展開した後に、下記を実行すればいい。

execute "#{fetch :deploy_to}html/app/Console/cake Migrations.migration run all"

githubのアクセス可能なリポジトリを限定する

EC2サーバにデプロイしたい。Githubは沢山リポジトリがあるが、今回デプロイ対象になっているリポジトリのみEC2からアクセスできるようにしたい。

githubのdeploy keysに公開鍵を登録しておけば、リポジトリが限定できました。
capistranoでデプロイする為に、EC2で公開鍵を作成して、それをdeploy keysに登録しました。そして、~/.ssh/configで下記のように設定しました。これでデプロイができました。

Host github.com
    HostName        github.com
    IdentityFile    ~/.ssh/id_rsa_hogehoge
    User            ec2-user

EC2にcapistrano3でデプロイ

EC2はサクラレンタルサーバと違ってデフォルトですんなりいけた。

EC2の/var/wwwにデプロイする。
/var/www/htmlに/var/www/currentのシンボリックリンクをはっておく。

capistranoサーバで下記設定する。
任意のディレクトリhogeに移動する。

cd hoge
cap install .
vim config/deploy.rb

config/deploy.rb

lock '3.1.0'
set :application, 'hoge'
set :repo_url, 'git@github.com:hoge/hoge.git'
set :deploy_to, '/var/www/'
set :pty, true

namespace :deploy do

  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      execute "cp -f #{fetch :deploy_to}database.php #{fetch :deploy_to}html/app/Config/"
      execute "cp -f #{fetch :deploy_to}core.php #{fetch :deploy_to}html/app/Config/"
      execute "cp -f #{fetch :deploy_to}.htaccess #{fetch :deploy_to}html/"
      execute "cp -f #{fetch :deploy_to}.htpasswd #{fetch :deploy_to}html/"
      execute "sudo chmod -R 707 #{fetch :deploy_to}html/app/tmp"
    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/staging.rb

role :app, %w{ec2-user@hoge.amazonaws.com}
role :web, %w{ec2-user@hoge.amazonaws.com}
role :db, %w{ec2-user@hoge.amazonaws.com}
server 'hoge.amazonaws.com', user: 'ec2-user', roles: %w{web app}, my_property: :my_value

set :ssh_options, {
  keys: %w(/root/.ssh/hoge.pem),
  forward_agent: true,
}

capistrano3でさくらレンタルサーバにGItHubのリポジトリをデプロイする

さくらレンタルサーバは環境変数設定ができず、capistrano3のデフォルトでgitリポジトリをデプロイしようとすると、GIT_ASKPASSという環境変数を設定しようとしてエラーになります。なのでデフォルトの機能を使わずにやってみます。

やることは、デプロイするサーバにsshで入って、pull用のディレクトリに移動して、githubリポジトリをpullします。データベース設定ファイルなどを入れ替えて、tmpディレクトリ内の不要ファイルなどを削除します。最後にドキュメントルートディレクトリに、pull用ディレクトリのシンボリックリンクをはります。まあ、これだともはやpull用とドキュメントルートを分ける必要がないと思いますが、capistranoのデフォルトの仕組みをつくるのが今めんどくさいですし、あくまで開発サーバなのでいいことにします。

mkdir hoge
cd hoge
cap install
vim config/deploy.rb

デフォルトの内容を削除して、下記だけにします。

framework_tasks = [:starting, :started, :updating, :updated, :publishing, :published, :finishing, :finished]

framework_tasks.each do |t|
  Rake::Task["deploy:#{t}"].clear
end

Rake::Task[:deploy].clear

set :application, 'hoge'
set :repo_url, 'git@github.com:hoge/hoge.git'
set :log_level, :debug

vim config/deploy/staging.rb

set :user, "hoge"
set :pull_path, "/home/#{fetch :user}/cap/#{fetch :application}"
set :deploy_path, "/home/#{fetch :user}/www/#{fetch :application}"
server "hoge.com", user: fetch( :user), roles: %w{web}

set :ssh_options, {
  keys: %w(/hoge/.ssh/id_rsa),
  forward_agent: true,
}

task :git_pull do
  on roles(:web) do
      execute "cd #{fetch :pull_path}; git pull"
  end
end

task :deploy => :git_pull do
  on roles(:web) do
    execute "ln -sf #{fetch :pull_path} #{fetch :deploy_path}"
    execute "cp -f #{fetch :pull_path}/database.php #{fetch :pull_path}/app/Config/"
    execute "touch #{fetch :pull_path}/app/tmp/logs/empty; rm -rf #{fetch :pull_path}/app/tmp/logs/*"
    execute "touch #{fetch :pull_path}/app/tmp/cache/models/empty; rm -rf #{fetch :pull_path}/app/tmp/cache/models/*"
    execute "touch #{fetch :pull_path}/app/tmp/cache/persistent/empty; rm -rf #{fetch :pull_path}/app/tmp/cache/persistent/*"
  end
end

cap staging deploy

かなり色々な事前準備というか、特定の環境を前提にしたものでもあり、本番サーバとかだと絶対使えませんが、一応動きました。開発サーバにsshで入ってgit pullってやればいいことだし、githubのpushに連動もしてないので、これだけだとほぼ無意味かなと思いますが、capistrano3の使い方が大体分かってよかったです。

参考;入門 Capistrano 3 ~ 全ての手作業を生まれる前に消し去りたい超分かりやすかった。

capistrano 3

capistrano2を使っていましたが3を使うことにします。

capifyではなくcap installによって初期化します。
ぱっと見あんまり変わってないようで全然分かりませんし、参考ブログみつつやってもエラーでまくります。

cap staging deployとやると、下記エラーがでます。
Stage not set, please call something such as `cap production deploy`, where production is a stage you have defined.

cap -Tとやると、下記エラーがでます。
cap aborted!
Don’t know how to build task ‘load:defaults’

/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/gems/capistrano-3.1.0/lib/capistrano/dsl.rb:14:in `invoke'
/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/gems/capistrano-3.1.0/lib/capistrano/application.rb:47:in `load_imports'
/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/gems/capistrano-3.1.0/lib/capistrano/application.rb:24:in `load_rakefile'
/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/gems/capistrano-3.1.0/lib/capistrano/application.rb:15:in `run'
/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/gems/capistrano-3.1.0/bin/cap:3:in `<top (required)>'
/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/bin/cap:23:in `load'
/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/bin/cap:23:in `<main>'
/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/bin/ruby_executable_hooks:15:in `eval'
/usr/local/rvm/gems/ruby-2.0.0-p451@rails3/bin/ruby_executable_hooks:15:in `<main>'
(See full trace by running task with --trace)

悲しいです。

Capistrano 3: Setting a Default Stageここに何となくそれっぽいことが書いてあるので調べてみます。

あら、Capfileがある場所でやるとできるな。2の場合確かどこでもできたんだけどな。まあ解決したな。

staging.rbに下記を設定して、cap staging deployしてみたらエラーがでました。

role :app, %w{hoge@hoge.biz}
role :web, %w{hoge@hoge.biz}
role :db,  %w{hoge@hoge.biz}

server 'hoge.biz', user: 'hoge', roles: %w{web app}, my_property: :my_value

server 'hoge.biz',
   user: 'hoge',
   ssh_options: {
    keys: %w(/hoge/.ssh/id_rsa),
    forward_agent: true,
   }
DEBUG [725731e3] Command: ( GIT_ASKPASS=/bin/echo GIT_SSH=/tmp/hoge/git-ssh.sh /usr/bin/env git ls-remote git@github.com:hoge/hoge.git )
DEBUG [725731e3] GIT_ASKPASS=/bin/echo: Command not found.
DEBUG [725731e3] Finished in 0.067 seconds with exit status 1 (failed).

GIT_ASKPASSっていう環境変数に値を入れることができないのだ。これはcapistranoとか俺が悪いんじゃなくサクラサーバのレンタルサーバが環境変数の設定を禁止してるからか!何度もやっちゃったよ!

Capitstranoでデプロイする度に、ユーザが登録している画像が消えると困る件

当然困ります。

http://www.slideshare.net/T2J/capistrano-tips-tips
このページの22ページに解決策が書いてあります。これがよさげ。

(ちなみに、僕は今時点よりちょっと古いCapistranoを使っております。3ではありません。)

cakePHPでapp/webroot内に画像フォルダを作っている場合、(app/webroot/uploadsなど)まず最新リリースのuploadsフォルダを、shared/system/uploadsにコピーします。
そして、今後はデプロイする度に、app/webroot/uploadsを、shared/system/uploadsフォルダのシンボリックリンクにする。
という感じにしたらいいらしい。

でも今全然正しくシンボリックリンクの設定ができてなかったのにdeployしても画像が共有されているのはなぜだろうか???
謎すぎる。

シンボリックリンクをcapistranoで作成するには、下記のような感じにした。

run "rm -rf #{latest_release}/app/webroot/uploads"
run "ln -nfs #{shared_path}/system/uploads #{latest_release}/app/webroot"

uploadsフォルダを削除してからじゃないとエラーになるので、最初に削除してから新たにシンボリックリンクを作成した。ln -nfsとあるが、nオプションは不要かも。というかfオプションも不要か削除してるし。

githubにpushするとcapistranoと連動して自動デプロイする

githubにはPost-Receive Hooksという機能があり、これはpushされると、登録したurlにpostアクセスし、json形式でpushしたデータの内容を渡してくれる。なので、このgithubからのpostアクセスを受け付けて、pushデータ内容に応じて、capistranoのサーバにアクセスしcapistranoでデプロイをするようにすれば、pushからの自動デプロイが可能になる。

PHPでGitHubからのpostアクセスの受けをつくる

今回はcapistranoと同じサーバにGitHubのpostアクセスの受けをつくった。ちなみにさくらのvpsサーバ。
apacheの設定をしてgithubから受けられるようにする。受けのphpは下記のような感じにした。

<?php
if(! isset($_POST['payload'])) die();

$payload = json_decode($_POST['payload']);
if(! (isset($payload->repository->url) && $payload->repository->url == 'https://github.com/hogehoge')){
    die();
}

chdir('../cap/hoge');
shell_exec('cap dev deploy');

githubから来てるものに限定するとかするともっとよい。あと、ブランチに応じて、開発サーバデプロイと、本番サーバデプロイを分けるとかできる。まあでも本番デプロイは手動でもいいか。さくらvpsだとapacheのドキュメントルートは/var/www/htmlでして、そこに上記phpファイルを置いております。chdirはつまり/var/www/cap/hogeに移動しており、hoge上にcapistranoフォルダを作っており、そこでcap dev deployをしております。githubのpostアクセスを受けているのはapacheですので、cap dev deployしているのもapacheになります。なので、apache君のssh pubkeyを作ったりしました。あとデプロイサーバのssh pubkeyもgithubに登録しました。僕のcapistranoはどこかで調べてconfig/deploy.rb以外に、config/deploy/dev.rbというのもありますので、それぞれ下記のような内容にしました。ちなみにデプロイサーバもサクラのレンタルサーバです。

config/deploy.rb

require "capistrano/ext/multistage"
require "capistrano_colors"
require "railsless-deploy"
require "rubygems"

ssh_options[:forward_agent] = false
set :normalize_asset_timestamps, false
set :use_sudo, false
default_run_options[:pty]   = true

#ステージ
set :stages, ["dev", "pro"]
set :default_stage, "dev"
# バージョン管理
set :scm, :git
set :scm_passphrase, "hogehogehoge"
# リポジトリ
set :repository, "git@github.com:hogeo/hoge.git"
# ブランチ
set :branch, "dev"
# デプロイ方式
#set :deploy_via, :remote_cache
#世代管理
set :keep_releases, 1 

# デプロイ対象外ファイル
set :copy_exclude, [".git", ".gitignore"]

config/deploy/dev.rb

# アプリケーション名
set :application, "hoge"
# デプロイ先ディレクトリ
set :deploy_to, "/home/hogeo/www/#{application}"

# デプロイサーバー
role :web, "hogeo@hogeo.sakura.ne.jp"
role :app, "hogeo@hogeo.sakura.ne.jp"

#ユーザアカウント
set:user, "hogeo"
set:password, "hogehogehoge"

set :scm_passphrase, "hogehoge"

namespace :deploy do
  before "deploy" do
    try_sudo "chown -R hogeo:users #{deploy_to}"
  end
end

after "deploy", "upload_config"

desc "各種セットアップ情報をアップロードします"
task :upload_config, roles => :web do
 run "cp -f /home/hogeo/www/hoge/database.php #{latest_release}/app/Config/."
 run "chmod -R 755 #{deploy_to}/current/"
 run "rm -rf #{latest_release}/app/tmp/cache/persistent/*"
 run "rm -rf #{latest_release}/app/tmp/cache/models/*"
 run "rm -rf #{latest_release}/app/tmp/logs/*"
end

参考
Webサイトをgithubで管理してpush時に自動的に同期する方法
GitHubとJenkins連動 自動デプロイ 開発環境設定編
githubにPushしたらwebhooksとSinatraを利用してサイトを自動的に更新する
GithubにあるプライベートリポジトリをCapistranoでデプロイ

capistranoのバージョン戻す

capistrano3.0.0以降は結構色々変わるらしく、勉強工数が必要なのと、今まで全く問題なかったのでバージョン戻してみることにした。3.0.1にアップデートしたらエラーだらけになったので。

sudo gem install capistrano -v 2.5.5
sudo gem uninstall -v 3.0.1 capistrano

これで、エラーなくなった。

Capistranoでssh接続

ssh接続する場合、下記のように設定できる。

# sshでログインするユーザ
set :user, "ユーザー"
# ssh 公開鍵設定
set :ssh_options, :port=>ポート, :forward_agent=>false, :keys=>"秘密鍵のパス", :passphrase => "パスフレーズ"
# コマンド実行時にsudoをつけるか
set :use_sudo, false
# デプロイサーバー
role :web, "ホスト"
role :app, "ホスト"

capistrano 使い方メモ cakePHP

もう忘れていたのでメモ。。

まずはプロジェクト用のフォルダ(例:myapp)をつくります。
myappに移動します。
capifyします。
configディレクトリに移動します。
deployディレクトリをつくります。

mkdir myapp
cd myapp
capify .
mkdir config/deploy
touch config/deploy/dev.rb

次に、config/deploy.rbと、config/deploy/development.rbとか、config/deploy/production.rbとかの中身をつくる。

config/deploy.rb

require "capistrano/ext/multistage"
require "capistrano_colors"
require "railsless-deploy"
require "rubygems"

ssh_options[:forward_agent] = true
set :normalize_asset_timestamps, false
set :use_sudo, false

#ステージ
set :stages, ["dev", "pro"]
set :default_stage, "dev"
# バージョン管理
set :scm, :subversion
# リポジトリ
set :repository, "リポジトリの場所"
# ブランチ
#set :branch, :master
# デプロイ方式
set :deploy_via, :copy
#世代管理
set :keep_releases, 3

# デプロイ対象外ファイル
set :copy_exclude, [".svn", "**/.svn",".svn/*"]

config/deploy/dev.rb

# アプリケーション名
set :application, "アプリ名"
# デプロイ先ディレクトリ
set :deploy_to, "デプロイ先ディレクトリパス/#{application}"

# デプロイサーバー
role :web, "ユーザ@ホスト"
role :app, "ユーザ@ホスト"

#ユーザアカウント
set:user, "ユーザ"
set:password, "パスワード"

namespace :deploy do
  before "deploy" do
    try_sudo "chown -R 所有者:グループ #{deploy_to}"
  end
end

after "deploy", "upload_config"

desc "各種セットアップ情報をアップロードします"
task :upload_config, roles => :web do
  run "rm -f #{latest_release}/app/Config/core.php"
  run "rm -f #{latest_release}/app/Config/bootstrap.php"
  run "rm -f #{latest_release}/app/Config/database.php"
  run "rm -f #{latest_release}/app/Config/email.php"
  run "rm -f #{latest_release}/app/Config/core.pro.php"
  run "rm -f #{latest_release}/app/Config/bootstrap.pro.php"
  run "rm -f #{latest_release}/app/Config/database.pro.php"
  run "rm -f #{latest_release}/app/Config/email.pro.php"
  run "mv -f #{latest_release}/app/Config/core.dev.php #{latest_release}/app/Config/core.php"
  run "mv -f #{latest_release}/app/Config/bootstrap.dev.php #{latest_release}/app/Config/bootstrap.php"
  run "mv -f #{latest_release}/app/Config/database.dev.php #{latest_release}/app/Config/database.php"
  run "mv -f #{latest_release}/app/Config/email.dev.php #{latest_release}/app/Config/email.php"
  run "chmod -R 755 #{deploy_to}/current/"
end

次に、デプロイ先の初期セットアップをする。デプロイ先のサーバに必要なフォルダなどをつくってくれる。

cap dev deploy:setup

あとは、デプロイしたいときに、デプロイする。

cap dev deploy