はじめに
最近、現在開発中のアプリケーションのステージング環境の構築を行なっています。
それにあたり、初めて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
Cpistranoについて
Capistranoはデプロイを自動化するフレームワークです。
Railsのほか、JavaやPHPで書かれたアプリケーションのデプロイにも使われます。
https://github.com/capistrano/capistrano
導入
Gemのインストール
Gemfileに下記のgemを追加してbundle installします。
1 2 3 4 5 6 7 8 9 | 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の設定ファイルを作成します。
1 | $ bundle exec cap install |
このコマンドを実行すると、下記の通り設定ファイルが作成されます。
1 2 3 4 5 6 7 8 9 | ├── Capfile ├── config │ ├── deploy │ │ ├── production.rb │ │ └── staging.rb │ └── deploy.rb └── lib └── capistrano └── tasks |
デプロイ設定
Capfileを修正する
生成されたCapfileを下記の通り修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # 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に記述します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | # 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を修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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) } |
Unicornの設定
下記の通り、config/unicorn/staging.rbを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 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 |
実行
ターミナルで下記のコマンドを実行します。
1 | $ bundle exec cap staging deploy |
さいごに
ステージング環境の構築にあたり、Capistranoによるデプロイの設定をまとめました。