地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【Ruby】Capistranoを使ってみる

github.com

背景

Capistranoってなんやねんレベルでコマンドだけ打って便利さを感じつつも何も理解してなかったので調べた際のメモ。「JenkinsとかGitHub Actionsででシェルスクリプトでデプロイじゃー!」ぐらいしかやったことレベル感で書いてます。(jenkinsだとDSLあった気がするけど使ったことない)

capistranorb.com

Capistranoとは

Capistranoは、デプロイスクリプトを使用してアプリケーションをデプロイするためのツール。デプロイを実行するには、事前定義されたタスクを使用するか、カスタム Rake タスクを準備する必要がある。複数のサーバー上でスクリプトを実行するためのオープンソースのツールでありイメージ的には「大量にsshしてサーバ上でなんかする」みたいなことをタスクとして定義しておいて使いまわせるよねってイメージ。

ja.wikipedia.org

wikipediaも存在していた。ただのssh便利ツールではなさそうという印象を持った。

Capistranoはおおまかに以下の3要素から構成されています。

  • capコマンド
  • Capistranoのライブラリ
  • デフォルトのデプロイタスク

Capistranoのライブラリやデフォルトのタスクを利用して設定ファイルを記述して、それをcapコマンドで実行する。そうするとCapistranoがもろもろの操作を自動的に行なってくれるという仕組み。

使ってみる

ざっくりとした流れは以下の感じです。事前にrubyでの開発環境のセットアップが前提となっている点がちょっと注意が必要ですね。

  • Capistranoのインストール
  • 設定ファイルのひな形をつくる
  • 設定ファイルのカスタマイズ
  • capコマンドを実行する

ここから下が具体的な手順となる。

source 'https://rubygems.org'
gem 'capistrano', '~> 3.16.0'

bundlerを使ってインストールする

$ bundle install --path vendor/bundle
$ bundle exec cap install

実行することで以下のようにCapfile(capistrano設定ファイル)が生成されます。全体の設定ファイルはconfig配下に生成されます。

require "capistrano/setup"
require "capistrano/deploy"

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 }

config/deploy.rbが全体の設定ファイル。(Capistranoにはデフォルトで「deploy」というタスクと、それが呼び出す複数の「deploy:サブタスク」が定義される)。Capistranoデフォルトの枠組みの中でデプロイを行う場合は、「deploy:サブタスク」を再定義するだけでよいので便利

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

set :application, "my_app_name"
set :repo_url, "git@example.com:me/my_repo.git"

# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp

# Default deploy_to directory is /var/www/my_app_name
# set :deploy_to, "/var/www/my_app_name"

# Default value for :format is :airbrussh.
# set :format, :airbrussh

# 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

# Default value for :pty is false
# set :pty, true

# Default value for :linked_files is []
# append :linked_files, "config/database.yml"

# Default value for linked_dirs is []
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"

# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/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

# Uncomment the following to require manually verifying the host key before first deploy.
# set :ssh_options, verify_host_key: :secure
  • config/deploy/任意のステージ名.rb

任意のステージ名.rb」は本番環境・テスト環境・開発環境などの環境ごとに異なる設定やタスクを書きます。これは実行時に指定しておくことでステージ毎に実行したいソースを指定することができるといった仕組みです。

実行

$ bundle exec cap [production|staging] deploy

とかやることで定義されているタスクを実行することができます。

ssh keyのforwarding設定

git cloneするための秘密鍵を、デプロイ先のサーバーに設置せず、capistranoサーバーに設置してforwardingする方法。鍵を作成する手順は以下です。(結構忘れがちなやつで最近ハマりました。。)

$ ssh-keygen -t rsa

この鍵の公開鍵をGitに登録する。また、capistranoサーバーの~/.ssh/秘密鍵を設置する。capistranoを打つサーバーでssh-addする必要があります。

$ eval `ssh-agent`
$ ssh-add ~/.ssh/id_rsa

並列実行

Parallel execution
Deploying to a fleet of app servers? Capistrano can run each deployment task concurrently across those servers and uses connection pooling for speed.

並列実行もサポートしているらしい。

感想

今回書いた内容だと正直シェルスクリプトの方が簡単でメンテもしやすそうなレベル感でしたが例えば巨大なリポジトリで複雑な構成なんかになってくるとシェルスクリプトだけでメンテナンスしてくのは困難になります。そういった時にCapistranoを知っている人同士であれば、他人の書いたデプロイ設定も読みやすく、結果的に保守や引き継ぎがしやすくなりするのかなと思いました。

また再利用の観点だったりrubyのパッケージとして配置するみたいな使い方もできるのでプロジェクトを横断したデプロイが行えるのは良いなと感じました。(新メンバーの参画でデプロイスクリプトの開発環境整えるのが大変などの問題がありますがそういうのが解決されそう。)