最近、現在開発中のアプリケーションのステージング環境の構築を行なっています。
それにあたり、初めてCapistranoの設定を行いましたので、ここに設定した内容をまとめます。
注意点としては、DBスキーマの管理にMigrationではなくridgepoleというGemを利用しています。
興味がある方はこちらの記事をご覧ください。
また、OctopusというGemを利用しています。
https://github.com/thiagopradi/octopus
ruby 2.4.1
rails 5.1.0
capistrano 3.8.1
unicorn 5.3.0
ar-octops (GitHubからインストール)
ridgepole 0.6.5
Capistranoはデプロイを自動化するフレームワークです。
Railsのほか、JavaやPHPで書かれたアプリケーションのデプロイにも使われます。
https://github.com/capistrano/capistrano
Gemfileに下記のgemを追加してbundle installします。
gem 'dotenv-rails' #環境変数を簡単に扱える group :development, :test do gem 'capistrano' gem 'capistrano-rails' gem 'capistrano-rbenv' gem 'capistrano-bundler' gem 'capistrano3-ridgepole' # Capistranoでridgepoleを扱う gem 'capistrano3-unicorn' # Unicornの起動を簡単に行える end
下記のコマンドを実行してCapistranoの設定ファイルを作成します。
$ bundle exec cap install
このコマンドを実行すると、下記の通り設定ファイルが作成されます。
├── Capfile ├── config │ ├── deploy │ │ ├── production.rb │ │ └── staging.rb │ └── deploy.rb └── lib └── capistrano └── tasks
生成されたCapfileを下記の通り修正します。
# Load DSL and set up stages require 'capistrano/setup' # Include default deployment tasks require 'capistrano/deploy' require 'capistrano/rbenv' set :rbenv_type, :my_app_name set :rbenv_ruby, '2.4.1' require 'capistrano/bundler' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' # ridgepoleの動作に必要 require 'capistrano3/ridgepole' # unicornの起動を簡単に行える require 'capistrano3/unicorn' # リポジトリにGitを利用する require 'capistrano/scm/git' install_plugin Capistrano::SCM::Git # Load custom tasks from `lib/capistrano/tasks` if you have any defined Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
共通の設定はdeploy.rbに記述します。
# config valid only for current version of Capistrano lock '3.8.1' set :application, 'my-app-name' set :repo_url, 'git@github.com:aaaa/my-app-name.git' # Default deploy_to directory is /var/www/my_app_name set :deploy_to, '/home/engines/www/my-app-name' # You can configure the Airbrussh format using :format_options. # These are the defaults. # set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto set :format, :pretty set :log_level, :debug # Default value for :pty is false set :pty, true # Default value for linked_dirs is [] # append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system" set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets vendor/bundle} set :unicorn_pid, "#{shared_path}/tmp/pids/unicorn.pid" # ridgepole関連の設定 set :ridgepole_roles, :db set :ridgepole_schema_file, File.join(current_path, 'db/schemas', 'Schemafile') set :ridgepole_config_file, File.join(current_path, 'config', 'database.yml') # Default value for default_env is {} # set :default_env, { path: "/opt/ruby/bin:$PATH" } # Default value for keep_releases is 5 set :keep_releases, 3 # rbenvをシステムにインストールしたか? or ユーザーローカルにインストールしたか? set :rbenv_type, :user # :system or :user # rubyのversion set :rbenv_ruby, '2.4.1' 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} set :rbenv_roles, :all # default value # bundle installの並列実行数 set :bundle_jobs, 4 # ridgepole関連のタスク after 'deploy:publishing', 'deploy:restart' after 'deploy:publishing', 'ridgepole:ridgepole_apply' namespace :ridgepole do desc 'ridgepole apply' task :ridgepole_apply do invoke 'ridgepole:apply' end end #octopus関連のタスク namespace :deploy do desc 'Restart application' task :restart do on roles(:app) do if fetch(:stage).to_sym == :staging execute "cd #{current_path}/config; mv staging_shards.yml shards.yml" else execute "cd #{current_path}/config; mv production_shards.yml shards.yml" end end invoke 'unicorn:restart' end end
今回は開発環境の構築ですので、staging.rbを修正します。
set :stage, :staging set :rails_env, 'staging' set :ridgepole_env, fetch(:rails_env) set :unicorn_rack_env, 'deployment' set :branch, ENV['BRANCH_NAME'] || 'develop' set :migration_role, 'db' # xxx.xxx.xxx.xxx: サーバのIPアドレス # yyyy: 実行する際のユーザ server 'xxx.xxx.xxx.xxx', user: 'yyyy', roles: %w{web app db} # sshでログインする際の設定 # config/deploy/staging_deploy.keyでログインする set :ssh_options, { keys: ["#{File.dirname(__FILE__)}/../deploy/staging_deploy.key"], forward_agent: false, auth_methods: %w(publickey) }
下記の通り、config/unicorn/staging.rbを作成します。
app_path = '/home/engines/www/my-app-name' worker_processes 2 working_directory "#{app_path}/current" # This loads the application in the master process before forking # worker processes # Read more about it here: # http://unicorn.bogomips.org/Unicorn/Configurator.html preload_app true timeout 30 # This is where we specify the socket. # We will point the upstream Nginx module to this socket later on #listen "#{app_path}/tmp/sockets/unicorn.sock", :backlog => 64 listen '/tmp/unicorn.sock', :backlog => 64 pid "#{app_path}/shared/tmp/pids/unicorn.pid" # Set the path of the log files inside the log folder of the testapp stderr_path "#{app_path}/current/log/unicorn.stderr.log" before_exec do |server| ENV['BUNDLE_GEMFILE'] = "#{app_path}/current/Gemfile" end before_fork do |server, worker| defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! old_pid = "#{server.config[:pid]}.oldbin" if old_pid != server.pid begin sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU Process.kill(sig, File.read(old_pid).to_i) rescue Errno::ENOENT, Errno::ESRCH end end sleep 1 end after_fork do |server, worker| # https://github.com/thiagopradi/octopus/issues/59(octopus + unicorn) defined?(ActiveRecord::Base) and ActiveRecord::Base.connection_proxy.instance_variable_get(:@shards).each {|k,v| v.clear_reloadable_connections! } end
ターミナルで下記のコマンドを実行します。
$ bundle exec cap staging deploy
ステージング環境の構築にあたり、Capistranoによるデプロイの設定をまとめました。