LoginSignup
4
7

More than 3 years have passed since last update.

Capistranoで自動デプロイ

Last updated at Posted at 2020-01-07

Capistrano

前提条件

  • config 2.0.0
  • dotenv-rails 2.7.5
  • Capistrano 3.11.2
  • slackistrano >= 4.0.1
  • pushion passenger( Nginx

セットアップ

  • Capistranoのインストール
Terminal
$ bundle exec cap install STAGES=staging,production
bundler: command not found: cap
Install missing gem executables with `bundle install`

あら。まあそりゃそうです笑

command not found: capとなった場合

  • この場合、capistranoのGEMがインストールされていない為、GEMインストールを行う

  • Gemfileを開き、編集

Terminal

# Gemfileの編集
$ vi Gemfile
group :staging, :production do
  # Use Capistrano for deployment
  gem 'capistrano',                 '3.11.2'
  gem 'capistrano-rails',           '1.4.0'
  gem 'capistrano-rbenv',           '2.1.4 '
  gem 'capistrano-passenger',       '0.2.0'
  # 今回はSlack通知も行うため、便宜上載せています
  gem 'slackistrano', '>=4.0.1'
end
  • bundle install
Terminal

$ bundle _1.17.2_ install --path vendor/bundle
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
・・・
Fetching capistrano 3.11.2
Installing capistrano 3.11.2
Fetching capistrano-bundler 1.6.0
Installing capistrano-bundler 1.6.0
Fetching capistrano-passenger 0.2.0
Installing capistrano-passenger 0.2.0
Fetching capistrano-rails 1.4.0
Installing capistrano-rails 1.4.0
Fetching capistrano-rbenv 2.1.4
Installing capistrano-rbenv 2.1.4
・・・
Fetching slackistrano 4.0.1
Installing slackistrano 4.0.1
・・・
Bundle complete! 38 Gemfile dependencies, 148 gems now installed.
Bundled gems are installed into `./vendor/bundle`
Post-install message from capistrano-passenger:
==== Release notes for capistrano-passenger ====
passenger once had only one way to restart: `touch tmp/restart.txt`
Beginning with passenger v4.0.33, a new way was introduced: `passenger-config restart-app`

The new way to restart was not initially practical for everyone,
since for versions of passenger prior to v5.0.10,
it required your deployment user to have sudo access for some server configurations.

capistrano-passenger gives you the flexibility to choose your restart approach, or to rely on reasonable defaults.

If you want to restart using `touch tmp/restart.txt`, add this to your config/deploy.rb:

    set :passenger_restart_with_touch, true

If you want to restart using `passenger-config restart-app`, add this to your config/deploy.rb:

    set :passenger_restart_with_touch, false # Note that `nil` is NOT the same as `false` here

If you don't set `:passenger_restart_with_touch`, capistrano-passenger will check what version of passenger you are running
and use `passenger-config restart-app` if it is available in that version.

If you are running passenger in standalone mode, it is possible for you to put passenger in your
Gemfile and rely on capistrano-bundler to install it with the rest of your bundle.
If you are installing passenger during your deployment AND you want to restart using `passenger-config restart-app`,
you need to set `:passenger_in_gemfile` to `true` in your `config/deploy.rb`.
================================================
  • CapistranoとCapifyアプリケーションをインストールする
Terminal

$ bundle exec cap install STAGES=staging,production
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

階層構造は以下となる

Tree-map
[rails app root]
├─ Capfile
├─ config
│ ├─ deploy
│ │ ├─production.rb
│ │ └─staging.rb
│ └─deploy.rb
└─ lib
  └─capistrano
    └─tasks
  └─tasks

capistranoをインストールしたので、capistrano/setup と capistrano/deploy の準備は一旦はこれでできました

capistrano/deploy タスク

  • デプロイを自動化する、capistranoのタスクです

Deployタスクの一覧

実行順 タスク名 意味
1 deploy Deploy実行
2 deploy:starting Deploy実行開始、サーバー待機中
2.1 deploy:check -
2.1.1 #{scm}:check -
2.1.2 deploy:check:directories -
2.1.3 deploy:check:linked_dirs -
2.1.4 deploy:check:make_linked_dirs -
2.1.5 deploy:check:linked_files -
2.2 deploy:set_previous_revision -
3 deploy:started Deploy開始中
4 deploy:updating Deploy実行中
4.1 #{scm}:create_release -
4.2 deploy:symlink:shared -
4.2.1 deploy:symlink:linked_files -
4.2.2 deploy:symlink:linked_dirs -
5 deploy:updated 更新完了
6 deploy:publishing デプロイ処理中
6.1 deploy:symlink:release -
7 deploy:published デプロイ処理終了
8 deploy:finishing デプロイ終了中、サーバークリーンアップ中
8.1 deploy:cleanup -
9 deploy:finished 処理終了
9.1 deploy:log_revision -
実行順 タスク名 意味
1 deploy:rollback 前回リリースバージョンにロールバック
2 deploy:starting Deploy実行開始、サーバー待機中
3 deploy:started Deploy開始中
4 deploy:reverting 前回リリースバージョンにrevert完了
5 deploy:reverted 前回リリースバージョンにrevert
6 deploy:publishing デプロイ処理中
7 deploy:published デプロイ処理終了
8 deploy:finishing_rollback ロールバック完了
9 deploy:finished 処理終了
実行順 タスク名 意味
1 install Capistranoインストール
(凡例:cap install STAGES=staging,production)

プラグインによるフローの追加

capistrano/rails/assets

  • Assetsのプリコンパイルを行う
インストール
Capfile
require capistrano/rails/assets
実行順 タスク名 意味
5 deploy:updated 更新完了
5.1 deploy:compile_assets 追加される
5.1.1 deploy:assets:precompile 追加される
5.1.2 deploy:assets:backup_manifest 追加される
5.2 deploy:normalize_assets 追加される

capistrano/rails/migrations

  • DBMigrationを行う
インストール
Capfile
require "capistrano/rails/migrations"
実行順 タスク名 意味
5 deploy:updated 更新完了
5.1 deploy:migrate 追加される

capistrano/npm

  • npm installを行う
インストール
Capfile
require "capistrano/rails/migrations"
実行順 タスク名 意味
4 deploy:updating Deploy実行中
4.1 #{scm}:create_release -
4.2 deploy:symlink:shared -
4.2.1 deploy:symlink:linked_files -
4.2.2 deploy:symlink:linked_dirs -
5 npm:install 追加される

前提条件

  • ssh-agentを使用

セットアップ手順

  • config/settings/staging.yml を作成
  • config/environments/staging.rb を作成
  • Capfile を編集する
Capfile
# Load DSL and set up stages
require "capistrano/setup"

# Include default deployment tasks
require "capistrano/deploy"

# Load the SCM plugin appropriate to your project:
#
# require "capistrano/scm/hg"
# install_plugin Capistrano::SCM::Hg
# or
# require "capistrano/scm/svn"
# install_plugin Capistrano::SCM::Svn
# or
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git

# Include tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
#   https://github.com/capistrano/rvm
#   https://github.com/capistrano/rbenv
#   https://github.com/capistrano/chruby
#   https://github.com/capistrano/bundler
#   https://github.com/capistrano/rails
#   https://github.com/capistrano/passenger
#
# require "capistrano/rvm"
# require "capistrano/rbenv"
# require "capistrano/chruby"
# require "capistrano/bundler"
# require "capistrano/rails/assets"
# require "capistrano/rails/migrations"
# require "capistrano/passenger"
# if you used rbenv
require "capistrano/rbenv"

require 'capistrano/rails'

require 'capistrano/bundler'

# 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/deploy.rb

# config valid for current version and patch releases of Capistrano
lock "~> 3.11.2"

set :application, "%app name%"
set :repo_url, "git@github.com:****/*****.git"

# Default branch is :master
# masterで良いので、特に変更は不要
ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
# bundle exec cap %env% deploy BRANCH=feature/hogehoge
# set :branch, ENV['BRANCH'] || 'master'

# Default deploy_to directory is /var/www/my_app_name
# set :deploy_to, "/var/www/my_app_name"
set :deploy_to, "/var/www/#{fetch(:application)}"

# Default value for :format is :airbrussh.
# set :format, :airbrussh
# Configure version management tool
set :scm, :git

# 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
# Configure log_leve if you output the log file
# set :format, :pretty
# set :log_level, :info

# Default value for :pty is false
# set :pty, true
# sudoを使用する場合はtrue
set :pty, true

# Default value for :linked_files is []
# append :linked_files, "config/database.yml"
# ln -s deploy_to/shared/config/database.yml :deploy_to/current/config/database.yml
set :linked_files, %w{config/database.yml}

# Default value for linked_dirs is []
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"
# sharedのディレクトリをcurrentにシンボリックリンクする
#set :linked_dirs, %w{bin log tmp/backup tmp/pids tmp/cache tmp/sockets vendor/bundle}
# binはrails consoleが必要なため、残す
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle')
set :rbenv_map_bins, %w{rake gem bundle ruby rails}

# Default value for default_env is {}
# capistrano用bundleするのに必要
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
set :default_env, { path: "/usr/local/rbenv/shims:/usr/local/rbenv/bin:$PATH" }

# Default value for local_user is ENV['USER']
# set :local_user, -> { `git config user.name`.chomp }

# Default value for keep_releases is 5
# set :keep_releases, 5
# How many keep the component of deployed in the "releases" directory
set :keep_releases, 5

# Uncomment the following to require manually verifying the host key before first deploy.
# set :ssh_options, verify_host_key: :secure
# Configure ssh agent
set :ssh_options, {
  keys: %w(~/.ssh/id_rsa),
  forward_agent: true,
  auth_methods: %w(publickey)
}

# Configure ur Slack's Incoming Webhook
# if you want to be disable deployment notifications to a specific stage by setting the :slackistrano configuration variable to false instead of actual settings.
set :slackistrano, false
#set :slackistrano, {
#  klass:   Slackistrano::CustomMessaging,
#  channel: '#chatops-#{fetch(:application)}-deploy',
#  webhook: 'https://hooks.slack.com/services/*/*/*'
#}

# Have you installed rbenv in the global area? Or was it installed in the user local area?
# :system or :user
set :rbenv_type, :user
# rubyのversion
set :rbenv_ruby, '2.6.5'
set :rbenv_path, '/usr/local/rbenv'
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

# Configure 
# rollback / deployを判定する為、before startingのcallbackで判定を取得する
# 参考:https://github.com/capistrano/capistrano/blob/v3.11.2/lib/capistrano/tasks/framework.rake#L57
before 'deploy:starting', 'slack:deploy:updating'

# https://github.com/capistrano/capistrano/blob/v3.11.2/lib/capistrano/dsl/task_enhancements.rb#L51
# https://www.rubydoc.info/github/capistrano/capistrano/Capistrano/TaskEnhancements
# 既存処理をOverride
module Capistrano
  module TaskEnhancements
    def exit_deploy_because_of_exception(ex)
      set :failed_exception, ex
      super ex
    end
  end
end

# Edited deploy task
namespace :deploy do

  desc 'git confirm'
  task :git_confirm do
    on release_roles :all do

      current = `git rev-parse --abbrev-ref HEAD`.chomp
      correct = fetch(:branch) || 'master'
      unless current == correct
        error "git: current branch is not '#{correct}' but '#{current}'."
        exit 1
      end
      # gitにdiffがないかどうかのチェック
      git_diff = `git diff`
      unless git_diff.empty?
        error "git: current source has any diff. \n#{git_diff}"
        exit 1
      end
    end
  end

  # 上記linked_filesで使用するファイルをアップロードするタスク
  desc 'Upload database.yml'
  task :upload do
    on roles(:app) do |host|
      if test "[ ! -d #{shared_path}/config ]"
        execute "mkdir -p #{shared_path}/config"
      end
      upload!('config/database.yml', "#{shared_path}/config/database.yml")
    end
  end

  desc 'Restart application'
  task :restart do
    # on roles(:app) do
    #   invoke 'unicorn:restart'
    # end
    on roles(:app), in: :sequence, wait: 5 do
      # Your restart mechanism here, for example:
      execute :touch, release_path.join('tmp/restart.txt')
    end
  end

  desc '.env publishing'
  task :env_publising do
    on roles(:app) do |host|
      if test "[ -f #{fetch(:deploy_to)}/.env ]"
        execute "cp -a #{fetch(:deploy_to)}/.env #{fetch(:release_path)}/.env"
      end
    end
  end
end

before 'deploy', 'deploy:git_confirm'
before 'deploy:starting', 'deploy:upload'
  # Enhance dotenv
after  'deploy:published', 'deploy:env_publising'
after  'deploy:published', 'deploy:restart'
  1. 各環境のデプロイ用ファイルの編集
config/deploy/stating.rb
# server-based syntax
# ======================
# Defines a single server with a list of roles and multiple properties.
# You can define all roles on a single server, or split them:

# server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value
# server "example.com", user: "deploy", roles: %w{app web}, other_property: :other_value
# server "db.example.com", user: "deploy", roles: %w{db}



# role-based syntax
# ==================

# Defines a role with one or multiple servers. The primary server in each
# group is considered to be the first unless any hosts have the primary
# property set. Specify the username and a domain or IP for the server.
# Don't use `:all`, it's a meta role.

# role :app, %w{deploy@example.com}, my_property: :my_value
# role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value
# role :db,  %w{deploy@example.com}



# Configuration
# =============
# You can set any configuration variable like in config/deploy.rb
# These variables are then only loaded and set in this stage.
# For available Capistrano configuration variables see the documentation page.
# http://capistranorb.com/documentation/getting-started/configuration/







# Custom SSH Options
# ==================
# You may pass any option but keep in mind that net/ssh understands a
# limited set of options, consult the Net::SSH documentation.
# http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start
#
# Global options
# --------------
#  set :ssh_options, {
#    keys: %w(/home/rlisowski/.ssh/id_rsa),
#    forward_agent: false,
#    auth_methods: %w(password)
#  }
#
# The server-based syntax can be used to override options:
# ------------------------------------
# server "example.com",
#   user: "user_name",
#   roles: %w{web app},
#   ssh_options: {
#     user: "user_name", # overrides user setting above
#     keys: %w(/home/user_name/.ssh/id_rsa),
#     forward_agent: false,
#     auth_methods: %w(publickey password)
#     # password: "please use keys"
#   }

set :stage, :staging
set :branch, ENV['GIT_BRANCH'] || `git rev-parse --abbrev-ref HEAD`.strip
set :rails_env, "staging"

# Only setup application server role
# role :app, %w{USER_NAME@IP_ADDRESS}

# capistrano_sample_app_v1
server "%hostname%", user: `whoami`.strip, roles: %w{app}
config/deploy/production.rb
# server-based syntax
# ======================
# Defines a single server with a list of roles and multiple properties.
# You can define all roles on a single server, or split them:

# server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value
# server "example.com", user: "deploy", roles: %w{app web}, other_property: :other_value
# server "db.example.com", user: "deploy", roles: %w{db}



# role-based syntax
# ==================

# Defines a role with one or multiple servers. The primary server in each
# group is considered to be the first unless any hosts have the primary
# property set. Specify the username and a domain or IP for the server.
# Don't use `:all`, it's a meta role.

# role :app, %w{deploy@example.com}, my_property: :my_value
# role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value
# role :db,  %w{deploy@example.com}



# Configuration
# =============
# You can set any configuration variable like in config/deploy.rb
# These variables are then only loaded and set in this stage.
# For available Capistrano configuration variables see the documentation page.
# http://capistranorb.com/documentation/getting-started/configuration/
# Feel free to add new variables to customise your setup.



# Custom SSH Options
# ==================
# You may pass any option but keep in mind that net/ssh understands a
# limited set of options, consult the Net::SSH documentation.
# http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start
#
# Global options
# --------------
#  set :ssh_options, {
#    keys: %w(/home/rlisowski/.ssh/id_rsa),
#    forward_agent: false,
#    auth_methods: %w(password)
#  }
#
# The server-based syntax can be used to override options:
# ------------------------------------
# server "example.com",
#   user: "user_name",
#   roles: %w{web app},
#   ssh_options: {
#     user: "user_name", # overrides user setting above
#     keys: %w(/home/user_name/.ssh/id_rsa),
#     forward_agent: false,
#     auth_methods: %w(publickey password)
#     # password: "please use keys"
#   }

set :stage, :production
set :branch, "master"
set :rails_env, "production"

role :app, %w{USER_NAME@IP_ADDRESS}
  • Slackistranoの設定
lib/slackistrano/custom_messaging.rb
if defined?(Slackistrano::Messaging)
   module Slackistrano
     class CustomMessaging < Messaging::Base

      # Suppress starting message.
      def payload_for_updating

        attachments = []
        # rollback / deployを判定する為、before startingのcallbackで判定を取得する
        title = fetch(:deploying, false) ? 'deploying' : 'rollback now'
        color = fetch(:deploying, false) ? 'warning' : 'danger'

        # https://github.com/phallstrom/slackistrano
        attachments = attachments_base(title: title, color: color)

        # git log
        attachments << {
          color:  color,
          title:  "git log",
          fields: git_last_commits_fields
        }

        return {attachments: attachments}
      end

      # Suppress updated message.
      def payload_for_updated
        attachments = [] + attachments_base(title: 'Deploy complete', color: 'good')
        return {attachments: attachments}
      end

      # Supperss reverting message.
      def payload_for_reverting
        # Delegate payload_for_updating
      end

      # Suppress reverted message.
      def payload_for_reverted
        attachments = [] + attachments_base(title: 'Revert complete', color: 'good')
        return {attachments: attachments}
      end

      # Suppress failred message.
      def payload_for_failed
        attachments = [] + attachments_base(title: 'Deploy failred', color: 'good')

        # エラー内容を取得
        exception = fetch(:failed_exception)
        trace_message = exception.inspect + "\n" + exception.backtrace.join("\n")

        # エラー内容
        attachments << {
          color: 'danger',
          title: "エラー内容",
          fields: [{
            value: trace_message
          }]
        }
        return {attachments: attachments}
      end

      private
        def attachments_base(title = "", color = "")
          {
            color: color,
            title: "#{application} #{title}",
            fields: [
              {
                title: '環境',
                value: stage,
                short: true
              },
              {
                title: 'ブランチ',
                value: branch,
                short: true
              },
              {
                title: 'Capistrano実行者',
                value: deployer,
                short: true
              },
              {
                title: '実行時間',
                value: elapsed_time,
                short: true
              }
            ],
            fallback: super[:text]
          }
        end

        def deployer
          `whoami`.strip
        end
    end
  end
end

変更の構成は以下の通り

Terminal
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

  modified:   Gemfile
  modified:   Gemfile.lock
  modified:   config/environments/development.rb
  modified:   config/environments/staging.rb
  modified:   config/environments/production.rb

Untracked files:
  (use "git add <file>..." to include in what will be committed)

  Capfile
  config/deploy.rb
  config/deploy/
  lib/slackistrano/

ADD

Terminal
$ git add Gemfile*
$ git add config/environments
$ git add Capfile
$ git add config/deploy*
$ git add lib/slackistrano
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

  new file:   Capfile
  modified:   Gemfile
  modified:   Gemfile.lock
  new file:   config/deploy.rb
  new file:   config/deploy/production.rb
  new file:   config/deploy/staging.rb
  modified:   config/environments/development.rb
  modified:   config/environments/production.rb
  new file:   lib/slackistrano/custom_messaging.rb

コミット&push

Terminal
$ git commit -m "Capistranoの設定"
[master 26dbe1b] Capistranoの設定
 9 files changed, 567 insertions(+), 3 deletions(-)
 create mode 100644 Capfile
 create mode 100644 config/deploy.rb
 create mode 100644 config/deploy/production.rb
 create mode 100644 config/deploy/staging.rb
 create mode 100644 lib/slackistrano/custom_messaging.rb

$ git push --set-upstream origin master
Enumerating objects: 23, done.
Counting objects: 100% (23/23), done.
Delta compression using up to 8 threads
Compressing objects: 100% (15/15), done.
Writing objects: 100% (16/16), 9.37 KiB | 3.12 MiB/s, done.
Total 16 (delta 6), reused 0 (delta 0)
remote: Resolving deltas: 100% (6/6), completed with 5 local objects.
To https://github.com/%organization%/%repos name%.git
   908k3a9..8u43k19  master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

SSH agentの設定

config/deploy/stating.rbserver で指定したホスト環境にSSH agentをセットアップする

Terminal
%hostname%]$ ssh-add -l
4096 SHA256:%masking% /home/%user%/.ssh/id_rsa (RSA)

詳細は ssh-agentの使い方 を参照

Slackistrano

  • Capistranoの自動デプロイをChatOpsに組み込みたいので、Incoming Webhookに連携します

セットアップ手順

  • config/deploy.rb を編集する
config/deploy.rb
# Configure ur Slack's Incoming Webhook
# if you want to be disable deployment notifications to a specific stage by setting the :slackistrano configuration variable to false instead of actual settings.
# When you desable slackistrano, comment out the description below.
set :slackistrano, false # falseの場合はslackistranoによるIncoming Webhookは発生しない
# set :slackistrano, { # こちらは発生する設定、上記かこちらのいずれかを記載する
#  klass:   Slackistrano::CustomMessaging,
#  channel: '#chatops-#{fetch(:application)}-deploy',
#  webhook: 'https://hooks.slack.com/services/*/*/*'
#}
  • Capfile を編集する
Capfile
・・・省略・・・
require 'capistrano/bundler'

# Require the slackistrano need the deploy.rb
require 'slackistrano/capistrano'

NameError: uninitialized constant Slackistrano::CustomMessaging が発生した場合

  • この場合、 Capfile にrequireでGemがロードされていないのが原因の為、Capfileを編集する

  • Capfileを開き、編集(上記セットアップ手順を忘れていることが考えられる)

デバッグ実行

  • 設定が一通り終わったら、次はデバッグ実行でチェックしてみます

  • --dry-run オプションで実行せずにデプロイをシミュレーションします

  • trace オプションでデプロイ実行中の例外スロー(スタックトレース?)をします

Terminal
$ bundle exec cap staging deploy --dry-run --trace
** Invoke staging (first_time)
** Execute staging
** Invoke load:defaults (first_time)
** Execute load:defaults
[Deprecation Notice] `set :scm, :git` is deprecated.
To ensure your project is compatible with future versions of Capistrano,
remove the :scm setting and instead add these lines to your Capfile after
`require "capistrano/deploy"`:
    require "capistrano/scm/git"
    install_plugin Capistrano::SCM::Git
** Invoke rbenv:validate (first_time)
** Execute rbenv:validate
** Invoke rbenv:map_bins (first_time)
** Execute rbenv:map_bins
** Invoke bundler:map_bins (first_time)
** Execute bundler:map_bins
** Invoke deploy:set_rails_env (first_time)
** Execute deploy:set_rails_env
** Invoke deploy:set_linked_dirs (first_time)
** Execute deploy:set_linked_dirs
** Invoke deploy:set_rails_env 
** Invoke deploy (first_time)
** Invoke deploy:git_confirm (first_time)
** Execute deploy:git_confirm
00:00 deploy:git_confirm
** Execute deploy
** Invoke deploy:starting (first_time)
** Invoke slack:deploy:starting (first_time)
** Execute slack:deploy:starting
** Invoke slack:deploy:updating (first_time)
** Execute slack:deploy:updating
** Invoke deploy:upload (first_time)
** Execute deploy:upload
00:00 deploy:upload
      01 mkdir -p /var/www/capistrano_sample_app_v1/shared/config
      02 config/database.yml /var/www/capistrano_sample_app_v1/shared/config/database.yml
** Execute deploy:starting
** Invoke deploy:check (first_time)
** Invoke git:check (first_time)
** Invoke git:wrapper (first_time)
** Execute git:wrapper
00:00 git:wrapper
      01 mkdir -p /tmp
      02 #<StringIO:0x00000000025f9838> /tmp/git-ssh-capistrano_sample_app_v1-staging-webmaster-patche.sh
      03 chmod 700 /tmp/git-ssh-capistrano_sample_app_v1-staging-webmaster-patche.sh
      04 #<StringIO:0x0000000002617720> /tmp/git-ssh-capistrano_sample_app_v1-staging-webmaster-patche.sh
** Execute git:check
00:00 git:check
      01 git ls-remote git@github.com:webmaster-patche/capistrano_sample_app_v1.git HEAD
** Execute deploy:check
** Invoke deploy:check:directories (first_time)
** Execute deploy:check:directories
00:00 deploy:check:directories
      01 mkdir -p /var/www/capistrano_sample_app_v1/shared /var/www/capistrano_sample_app_v1/releases
** Invoke deploy:check:linked_dirs (first_time)
** Execute deploy:check:linked_dirs
00:00 deploy:check:linked_dirs
      01 mkdir -p /var/www/capistrano_sample_app_v1/shared/bin /var/www/capistrano_sample_app_v1/shared/log /var/www/capistrano_sample_app_v1/shared/tmp/backup /var/www/capistrano_sample_app_v1/shared/tmp/pids /var/www/capistrano_sample_app_v1/shared/tmp/cache /var/www/capistrano_sample_app_v1/shared/t…
** Invoke deploy:check:make_linked_dirs (first_time)
** Execute deploy:check:make_linked_dirs
00:00 deploy:check:make_linked_dirs
      01 mkdir -p /var/www/capistrano_sample_app_v1/shared/config
** Invoke deploy:check:linked_files (first_time)
** Execute deploy:check:linked_files
** Invoke deploy:set_previous_revision (first_time)
** Execute deploy:set_previous_revision
** Invoke deploy:started (first_time)
** Execute deploy:started
** Invoke deploy:updating (first_time)
** Invoke deploy:new_release_path (first_time)
** Execute deploy:new_release_path
** Invoke git:create_release (first_time)
** Invoke git:update (first_time)
** Invoke git:clone (first_time)
** Invoke git:wrapper 
** Execute git:clone
00:00 git:clone
      The repository mirror is at /var/www/capistrano_sample_app_v1/repo
      The repository mirror is at /var/www/capistrano_sample_app_v1/repo
** Execute git:update
00:00 git:update
      01 git remote set-url origin git@github.com:webmaster-patche/capistrano_sample_app_v1.git
      02 git remote update --prune
** Execute git:create_release
00:00 git:create_release
      01 mkdir -p /var/www/capistrano_sample_app_v1/releases/*******
      02 git archive master | /usr/bin/env tar -x -f - -C /var/www/capistrano_sample_app_v1/releases/*******
** Invoke slack:deploy:updating 
** Execute deploy:updating
** Invoke deploy:set_current_revision (first_time)
** Invoke git:set_current_revision (first_time)
** Execute git:set_current_revision
** Execute deploy:set_current_revision
00:00 deploy:set_current_revision
      01 echo "" > REVISION
** Invoke deploy:symlink:shared (first_time)
** Execute deploy:symlink:shared
** Invoke deploy:symlink:linked_files (first_time)
** Execute deploy:symlink:linked_files
00:00 deploy:symlink:linked_files
      01 mkdir -p /var/www/capistrano_sample_app_v1/releases/*******/config
** Invoke deploy:symlink:linked_dirs (first_time)
** Execute deploy:symlink:linked_dirs
00:00 deploy:symlink:linked_dirs
      01 mkdir -p /var/www/capistrano_sample_app_v1/releases/******* /var/www/capistrano_sample_app_v1/releases/*******/tmp /var/www/capistrano_sample_app_v1/releases/*******/vendor /var/www/capistrano_sample_app_v1/releases/*******/public
** Invoke deploy:updated (first_time)
** Invoke bundler:install (first_time)
** Execute bundler:install
00:00 bundler:install
      The Gemfile's dependencies are satisfied, skipping installation
      The Gemfile's dependencies are satisfied, skipping installation
** Execute deploy:updated
** Invoke deploy:compile_assets (first_time)
** Invoke deploy:set_rails_env 
** Execute deploy:compile_assets
** Invoke deploy:assets:precompile (first_time)
** Execute deploy:assets:precompile
** Invoke deploy:assets:backup_manifest (first_time)
** Execute deploy:assets:backup_manifest
** Invoke deploy:cleanup_assets (first_time)
** Invoke deploy:set_rails_env 
** Execute deploy:cleanup_assets
** Invoke deploy:normalize_assets (first_time)
** Invoke deploy:set_rails_env 
** Execute deploy:normalize_assets
** Invoke deploy:migrate (first_time)
** Invoke deploy:set_rails_env 
** Execute deploy:migrate
** Invoke deploy:publishing (first_time)
** Execute deploy:publishing
** Invoke deploy:symlink:release (first_time)
** Execute deploy:symlink:release
00:00 deploy:symlink:release
      01 ln -s /var/www/capistrano_sample_app_v1/releases/******* /var/www/capistrano_sample_app_v1/releases/current
      02 mv /var/www/capistrano_sample_app_v1/releases/current /var/www/capistrano_sample_app_v1
** Invoke deploy:published (first_time)
** Execute deploy:published
** Invoke deploy:finishing (first_time)
** Execute deploy:finishing
** Invoke deploy:cleanup (first_time)
** Execute deploy:cleanup
** Invoke slack:deploy:updated (first_time)
** Execute slack:deploy:updated
** Invoke deploy:finished (first_time)
** Execute deploy:finished
** Invoke deploy:log_revision (first_time)
** Execute deploy:log_revision
00:00 deploy:log_revision
      01 echo "Branch master (at ) deployed as release 20200108015441 by webmaster-patche" >> /var/www/capistrano_sample_app_v1/revisions.log

実行

  • 設定が一通り終わったら、次はデバッグではなく実際に実行でチェックしてみます

  • trace オプションでデプロイ実行中の例外スロー(スタックトレース?)をします

Terminal
$ bundle exec cap staging deploy --trace
** Invoke staging (first_time)
** Execute staging
** Invoke load:defaults (first_time)
** Execute load:defaults
[Deprecation Notice] `set :scm, :git` is deprecated.
To ensure your project is compatible with future versions of Capistrano,
remove the :scm setting and instead add these lines to your Capfile after
`require "capistrano/deploy"`:

    require "capistrano/scm/git"
    install_plugin Capistrano::SCM::Git

** Invoke rbenv:validate (first_time)
** Execute rbenv:validate
** Invoke rbenv:map_bins (first_time)
** Execute rbenv:map_bins
** Invoke bundler:map_bins (first_time)
** Execute bundler:map_bins
** Invoke deploy:set_rails_env (first_time)
** Execute deploy:set_rails_env
** Invoke deploy:set_linked_dirs (first_time)
** Execute deploy:set_linked_dirs
** Invoke deploy:set_rails_env 
** Invoke deploy (first_time)
** Invoke deploy:git_confirm (first_time)
** Execute deploy:git_confirm
00:00 deploy:git_confirm
      [git:confirm] Skip git confirm
** Execute deploy
** Invoke deploy:starting (first_time)
** Invoke slack:deploy:starting (first_time)
** Execute slack:deploy:starting
** Invoke slack:deploy:updating (first_time)
** Execute slack:deploy:updating
** Invoke deploy:upload (first_time)
** Execute deploy:upload
00:00 deploy:upload
      Uploading config/database.yml 100.0%
** Execute deploy:starting
** Invoke deploy:check (first_time)
** Invoke git:check (first_time)
** Invoke git:wrapper (first_time)
** Execute git:wrapper
00:00 git:wrapper
      01 mkdir -p /tmp
    ✔ 01 %user%@%hostname% 0.139s
      Uploading /tmp/git-ssh-capistrano_sample_app_v1-staging-%user%.sh 100.0%
      02 chmod 700 /tmp/git-ssh-capistrano_sample_app_v1-staging-%user%.sh
    ✔ 02 %user%@%hostname% 0.142s
** Execute git:check
00:00 git:check
      01 git ls-remote git@github.com:%user%/capistrano_sample_app_v1.git HEAD
      01 78ee082f5b26fcac1ad4aa25410dcc3d1b32d51e HEAD
    ✔ 01 %user%@%hostname% 1.904s
** Execute deploy:check
** Invoke deploy:check:directories (first_time)
** Execute deploy:check:directories
00:02 deploy:check:directories
      01 mkdir -p /var/www/capistrano_sample_app_v1/shared /var/www/capistrano_sample_app_v1/releases
    ✔ 01 %user%@%hostname% 0.097s
** Invoke deploy:check:linked_dirs (first_time)
** Execute deploy:check:linked_dirs
00:02 deploy:check:linked_dirs
      01 mkdir -p /var/www/capistrano_sample_app_v1/shared/log /var/www/capistrano_sample_app_v1/shared/tmp/pids /var/www/capistrano_sample_app_v1/shared/tmp/cache /var/www/capistrano_sample_app_v1/shared/tmp/sockets /var/www/capistrano_sample_app_v1/shared/vendor/bundle /var/www/capistrano_sample_app_v1/shared/public/ass…
    ✔ 01 %user%@%hostname% 0.140s
** Invoke deploy:check:make_linked_dirs (first_time)
** Execute deploy:check:make_linked_dirs
00:02 deploy:check:make_linked_dirs
      01 mkdir -p /var/www/capistrano_sample_app_v1/shared/config
    ✔ 01 %user%@%hostname% 0.140s
** Invoke deploy:check:linked_files (first_time)
** Execute deploy:check:linked_files
** Invoke deploy:set_previous_revision (first_time)
** Execute deploy:set_previous_revision
** Invoke deploy:started (first_time)
** Execute deploy:started
** Invoke deploy:updating (first_time)
** Invoke deploy:new_release_path (first_time)
** Execute deploy:new_release_path
** Invoke git:create_release (first_time)
** Invoke git:update (first_time)
** Invoke git:clone (first_time)
** Invoke git:wrapper 
** Execute git:clone
00:03 git:clone
      The repository mirror is at /var/www/capistrano_sample_app_v1/repo
** Execute git:update
00:03 git:update
      01 git remote set-url origin git@github.com:%user%/capistrano_sample_app_v1.git
    ✔ 01 %user%@%hostname% 0.142s
      02 git remote update --prune
      02 Fetching origin
      02 remote: Enumerating objects: 12, done.
re…ote: Counting objects:  50% (6/12)
remote: Compressing objects: 100% (3/3), done.
      02 remote: Total 7 (delta 4), reused 7 (delta 4), pack-reused 0
Unpacking objects… 100% (7/7)    (1/7)   
      02 From github.com:%user%/capistrano_sample_app_v1
      02    1b9edaa..78ee082  master     -> master
    ✔ 02 %user%@%hostname% 2.175s
** Execute git:create_release
00:06 git:create_release
      01 mkdir -p /var/www/capistrano_sample_app_v1/releases/*******
    ✔ 01 %user%@%hostname% 0.139s
      02 git archive master | /usr/bin/env tar -x -f - -C /var/www/capistrano_sample_app_v1/releases/*******
    ✔ 02 %user%@%hostname% 0.154s
** Invoke slack:deploy:updating 
** Execute deploy:updating
** Invoke deploy:set_current_revision (first_time)
** Invoke git:set_current_revision (first_time)
** Execute git:set_current_revision
** Execute deploy:set_current_revision
00:06 deploy:set_current_revision
      01 echo "78ee082f5b26fcac1ad4aa25410dcc3d1b32d51e" > REVISION
    ✔ 01 %user%@%hostname% 0.140s
** Invoke deploy:symlink:shared (first_time)
** Execute deploy:symlink:shared
** Invoke deploy:symlink:linked_files (first_time)
** Execute deploy:symlink:linked_files
00:07 deploy:symlink:linked_files
      01 mkdir -p /var/www/capistrano_sample_app_v1/releases/*******/config
    ✔ 01 %user%@%hostname% 0.141s
      02 rm /var/www/capistrano_sample_app_v1/releases/*******/config/database.yml
    ✔ 02 %user%@%hostname% 0.138s
      03 ln -s /var/www/capistrano_sample_app_v1/shared/config/database.yml /var/www/capistrano_sample_app_v1/releases/*******/config/database.yml
    ✔ 03 %user%@%hostname% 0.145s
** Invoke deploy:symlink:linked_dirs (first_time)
** Execute deploy:symlink:linked_dirs
00:07 deploy:symlink:linked_dirs
      01 mkdir -p /var/www/capistrano_sample_app_v1/releases/******* /var/www/capistrano_sample_app_v1/releases/*******/tmp /var/www/capistrano_sample_app_v1/releases/*******/vendor /var/www/capistrano_sample_app_v1/releases/*******/public
    ✔ 01 %user%@%hostname% 0.142s
      02 rm -rf /var/www/capistrano_sample_app_v1/releases/*******/log
    ✔ 02 %user%@%hostname% 0.138s
      03 ln -s /var/www/capistrano_sample_app_v1/shared/log /var/www/capistrano_sample_app_v1/releases/*******/log
    ✔ 03 %user%@%hostname% 0.138s
      04 ln -s /var/www/capistrano_sample_app_v1/shared/tmp/pids /var/www/capistrano_sample_app_v1/releases/*******/tmp/pids
    ✔ 04 %user%@%hostname% 0.143s
      05 ln -s /var/www/capistrano_sample_app_v1/shared/tmp/cache /var/www/capistrano_sample_app_v1/releases/*******/tmp/cache
    ✔ 05 %user%@%hostname% 0.137s
      06 ln -s /var/www/capistrano_sample_app_v1/shared/tmp/sockets /var/www/capistrano_sample_app_v1/releases/*******/tmp/sockets
    ✔ 06 %user%@%hostname% 0.136s
      07 ln -s /var/www/capistrano_sample_app_v1/shared/vendor/bundle /var/www/capistrano_sample_app_v1/releases/*******/vendor/bundle
    ✔ 07 %user%@%hostname% 0.138s
      08 ln -s /var/www/capistrano_sample_app_v1/shared/public/assets /var/www/capistrano_sample_app_v1/releases/*******/public/assets
    ✔ 08 %user%@%hostname% 0.138s
** Invoke deploy:updated (first_time)
** Invoke bundler:install (first_time)
** Execute bundler:install
00:11 bundler:install
      01 RBENV_ROOT=/usr/local/rbenv RBENV_VERSION=2.6.5 /usr/local/rbenv/bin/rbenv exec bundle install --path /var/www/capistrano_sample_app_v1/shared/bundle --jobs 4 --without development test --deployment --quiet
    ✔ 01 %user%@%hostname% 0.701s
** Execute deploy:updated
** Invoke deploy:compile_assets (first_time)
** Invoke deploy:set_rails_env 
** Execute deploy:compile_assets
** Invoke deploy:assets:precompile (first_time)
** Execute deploy:assets:precompile
** Invoke deploy:assets:backup_manifest (first_time)
** Execute deploy:assets:backup_manifest
** Invoke deploy:cleanup_assets (first_time)
** Invoke deploy:set_rails_env 
** Execute deploy:cleanup_assets
** Invoke deploy:normalize_assets (first_time)
** Invoke deploy:set_rails_env 
** Execute deploy:normalize_assets
** Invoke deploy:migrate (first_time)
** Invoke deploy:set_rails_env 
** Execute deploy:migrate
** Invoke deploy:publishing (first_time)
** Execute deploy:publishing
** Invoke deploy:symlink:release (first_time)
** Execute deploy:symlink:release
00:11 deploy:symlink:release
      01 ln -s /var/www/capistrano_sample_app_v1/releases/******* /var/www/capistrano_sample_app_v1/releases/current
    ✔ 01 %user%@%hostname% 0.142s
      02 mv /var/www/capistrano_sample_app_v1/releases/current /var/www/capistrano_sample_app_v1
    ✔ 02 %user%@%hostname% 0.142s
** Invoke deploy:published (first_time)
** Execute deploy:published
** Invoke deploy:env_publising (first_time)
** Execute deploy:env_publising
00:12 deploy:env_publising
      01 cp -a /var/www/capistrano_sample_app_v1/.env /var/www/capistrano_sample_app_v1/releases/*******/.env
    ✔ 01 %user%@%hostname% 0.137s
** Invoke deploy:restart (first_time)
** Execute deploy:restart
00:12 deploy:restart
      01 touch /var/www/capistrano_sample_app_v1/releases/*******/tmp/restart.txt
    ✔ 01 %user%@%hostname% 0.137s
** Invoke deploy:finishing (first_time)
** Execute deploy:finishing
** Invoke deploy:cleanup (first_time)
** Execute deploy:cleanup
00:12 deploy:cleanup
      Keeping 5 of 6 deployed releases on %hostname%
      01 rm -rf /var/www/capistrano_sample_app_v1/releases/*******
    ✔ 01 %user%@%hostname% 0.149s
** Invoke slack:deploy:updated (first_time)
** Execute slack:deploy:updated
** Invoke deploy:finished (first_time)
** Execute deploy:finished
** Invoke deploy:log_revision (first_time)
** Execute deploy:log_revision
00:13 deploy:log_revision
      01 echo "Branch master (at 78ee082f5b26fcac1ad4aa25410dcc3d1b32d51e) deployed as release ******* by %user%" >> /var/www/capistrano_sample_app_v1/revisions.log
    ✔ 01 %user%@%hostname% 0.138s

Rails 5.2以上で気をつけなければならないこと

require': cannot load such file -- bootsnap/setup (LoadError). が発生する場合

  • 少なくともRails 5.2系では bootsnap はデフォルトで Gemfile に組み込まれている
Gemfile
group :development, :test do
  ・・・途中省略・・・

  # Reduces boot times through caching; required in config/boot.rb
  gem 'bootsnap', '>= 1.1.0', require: false
end

この状態では staging環境の起動失敗する

Terminal
$ bundle exec rails c -e staging
Traceback (most recent call last):
  13: from bin/rails:4:in `<main>'
  12: from bin/rails:4:in `require'
  11: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/commands.rb:18:in `<top (required)>'
  10: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/command.rb:46:in `invoke'
   9: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/command/base.rb:65:in `perform'
   8: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/thor-0.20.3/lib/thor.rb:387:in `dispatch'
   7: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/thor-0.20.3/lib/thor/invocation.rb:126:in `invoke_command'
   6: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/thor-0.20.3/lib/thor/command.rb:27:in `run'
   5: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/commands/console/console_command.rb:95:in `perform'
   4: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/command/actions.rb:14:in `require_application_and_environment!'
   3: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/command/actions.rb:22:in `require_application!'
   2: from /var/www/capistrano_sample_app_v1/shared/bundle/ruby/2.6.0/gems/railties-5.2.3/lib/rails/command/actions.rb:22:in `require'
   1: from /var/www/capistrano_sample_app_v1/releases/*******/config/application.rb:17:in `<top (required)>'
/var/www/capistrano_sample_app_v1/releases/*******/config/application.rb:17:in `require': cannot load such file -- bootsnap/setup (LoadError)
  • config/boot.rbを書き換える
config/boot.rb
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)

require 'bundler/setup' # Set up gems listed in the Gemfile.
begin
  require 'bootsnap/setup'
  env = ENV['RAILS_ENV'] || "development"
  Bootsnap.setup(
    cache_dir:            'tmp/cache',          # キャッシュファイルを保存する path
    development_mode:     env == 'development', # 現在の作業環境、例えば RACK_ENV, RAILS_ENV など。
    load_path_cache:      true,                 # キャッシュで LOAD_PATH を最適化する。
    autoload_paths_cache: true,                 # キャッシュで ActiveSupport による autoload を行う。
    disable_trace:        true,                 # (アルファ) `RubyVM::InstructionSequence.compile_option = { trace_instruction: false }`をセットする。
    compile_cache_iseq:   true,                 # ISeq キャッシュをコンパイルする
    compile_cache_yaml:   true                  # YAML キャッシュをコンパイルする
  )
rescue LoadError => e;
end # Speed up boot time by caching expensive operations.

リポジトリ

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7