Capistrano を導入する(メモ)

Capistranoを導入してみます。
前回作成した仮想マシンをターゲットに、デプロイします。

目次

参考

準備

bundle exec rails sで、いつもの「Yay! You’re on Rails!」が確認できるところまで進めます。
本番環境では、この画面は見れないので何かページを作って root を変えておきます。

Capistrano 導入

Capistrano インストール

Gemfile に以下を追記する。

1
2
3
group :development do
gem "capistrano", "~> 3.12", require: false
end

bundle installで capistrano をインストール。

Capfile を作る

次のコマンドを実行。

1
2
3
bundle exec cap install STAGES=production
#STAGESには、local,sandbox,qa,productionを与えることができるが、
#production以外は不要

以下のファイルが作成される。

1
2
Capfile
config/deploy/production.rb

deploy.rb を設定

config/deploy.rb に以下を記述。

config/deploy.rb
1
2
3
4
5
6
# config valid for current version and patch releases of Capistrano
lock "~> 3.12.1"

set :application, "testapp"
set :repo_url, "githubリポジトリのURL"
set :deploy_to, "/var/www/testapp"

production.rb を設定

config/deploy/production.rbに以下を記述。

config/deploy/production.rb
1
server "仮想マシンのIP", user: "sshログインユーザー名", roles: %w{app db web}

一旦確認

次のコマンドを実行する。

1
bundle exec cap production deploy

すると、ssh ログインのパスワードが確認できるので入力する。
ダバーッとメッセージが出るので、しばらく待つ。

エラーはないので、ssh ログインして見てみるとディレクトリが展開されているのがわかります。

1
2
3
4
5
[root@localhost ~]# ls /var/www/testapp
current releases repo revisions.log shared
[root@localhost ~]# ls /var/www/testapp/current/
Gemfile README.md Rakefile bin config.ru lib package.json storage tmp
Gemfile.lock REVISION app config db log public test vendor

rbenv の設定

rbenv / rbenvを参照しながら、デプロイ先サーバーに rbenv を導入。
以下の流れで導入しました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
yum install -y gcc bzip2 openssl-devel readline-devel zlib-devel
cd ~/.rbenv && src/configure && make -C src
cd ..
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
mkdir -p "$(rbenv root)"/plugins
source .bash_profile
mkdir -p "$(rbenv root)"/plugins
git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
rbenv init
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
source .bash_profile
which rbenv
>>/root/.rbenv/bin/rbenv
#開発環境が2.4.9だったので、そこに合わせておくことにした
rbenv install 2.4.9
rbenv rehash
rbenc local 2.4.9
ruby -v
>>ruby 2.4.9p362 (2019-10-02 revision 67824) [x86_64-linux]
gem install bundler

Capistrano-rbenv インストール

Gemfile を以下の様に編集。

1
2
3
4
5
#省略
group :development do
gem "capistrano", "~> 3.12", require: false
gem 'capistrano-rbenv', '~> 2.1'
end

bundle installで capistrano-rbenv をインストール。

Capfile と deploy.rb を編集1

Capfile にてcapistrano/rbenvのコメントアウトを外す。

Capfile
1
2
# コメントアウトを外す
require "capistrano/rbenv"

config/deploy.rb を以下のように編集。

config/deploy.rb
1
2
3
4
5
6
7
8
9
10
11
# config valid for current version and patch releases of Capistrano
lock "~> 3.12.1"

set :application, "testapp"
set :repo_url, "githubリポジトリのURL"
set :deploy_to, "/var/www/testapp"

# デプロイ先設定
set :rbenv_type, :user
set :rbenv_ruby, '2.4.9'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} #{fetch(:rbenv_path)}/bin/rbenv exec"

Capistrano-bundler インストール

Gemfile を以下の様に編集します。

1
2
3
4
5
6
#省略
group :development do
gem "capistrano", "~> 3.12", require: false
gem 'capistrano-rbenv', '~> 2.1'
gem 'capistrano-bundler', '~> 1.6'
end

bundle installで capistrano-bundler をインストール。

Capfile と deploy.rb を編集2

Capfile にてcapistrano/rbenvのコメントアウトを外す。

Capfile
1
2
# コメントアウトを外す
require "capistrano/rbenv"

config/deploy.rb を以下のように編集。

config/deploy.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# config valid for current version and patch releases of Capistrano
lock "~> 3.12.1"

# デプロイ先設定
set :application, "testapp"
set :repo_url, "git@github.com:Octo8080/captest.git"

# rbenv設定
set :rbenv_type, :user
set :rbenv_ruby, '2.4.9'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} #{fetch(:rbenv_path)}/bin/rbenv exec"

# bundler設定
set :linked_dirs, fetch(:linked_dirs, []) << '.bundle'

一旦確認

確認したら、エラー発生。
Your bundle only supports platforms ["x64-mingw32"] but your local platforms are...という表示。
手元で使っているのが win10 だが、デプロイ先を CentOS にしているので、プラットフォームが合わないということらしい。

stackoverflow のHow can I resolve “Your bundle only supports platforms [”x86-mingw32“] but your local platforms are [”ruby“, ”x86_64-linux“]”を参考にする。

以下を実行することで、gemfile.lockの中に別のプラットフォーム向けの gem を追加できるそう。

1
bundle lock --add-platform x86_64-linux

(以後 bundle install 後は毎回実施しています。)

終わったら github に push してbundle exec cap production deployを実行。

デプロイ先の
/var/www/testapp/shared/bundle/ruby/2.4.0/gems/をのぞくと、インストールされた gem を見ることができました。

/var/www/testapp/shared/bundle/ruby/2.4.0/gems/の結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@localhost ~]#ls /var/www/testapp/shared/bundle/ruby/2.4.0/gems/
activejob-5.2.4.2 concurrent-ruby-1.1.6 mini_mime-1.0.2 rb-inotify-0.10.1
activemodel-5.2.4.2 crass-1.0.6 mini_portile2-2.4.0 sass-3.7.4
activerecord-5.2.4.2 duktape-2.3.0.0 minitest-5.14.0 sass-listen-4.0.0
activesupport-5.2.4.2 enum_help-0.0.17 msgpack-1.3.3 sprockets-3.7.2
airbrussh-1.4.0 erubi-1.9.0 mysql2-0.5.3 sshkit-1.21.0
arel-9.0.0 execjs-2.7.0 net-scp-2.0.0 thor-1.0.1
bcrypt-3.1.13 ffi-1.12.2 net-ssh-5.2.0 thread_safe-0.3.6
bootsnap-1.4.6 globalid-0.4.2 nio4r-2.5.2 tilt-2.0.10
builder-3.2.4 i18n-1.8.2 nokogiri-1.10.9 turbolinks-5.2.1
capistrano-3.12.1 jbuilder-2.10.0 puma-3.12.4 turbolinks-source-5.2.0
capistrano-bundler-1.6.0 mail-2.7.1 rack-2.2.2 tzinfo-1.2.6
capistrano-rbenv-2.1.6 marcel-0.3.3 rack-test-1.1.0 uglifier-4.2.0
coffee-script-2.4.1 method_source-1.0.0 rake-13.0.1 websocket-driver-0.7.1
coffee-script-source-1.12.2 mimemagic-0.3.4 rb-fsevent-0.10.3 websocket-extensions-0.1.4

が、実行自体はエラー。
mysql-devel パッケージが足りないそうなので、sudo yum install -y mysql-develを実行。
bundle exec cap production deployを再度実行。

エラーなく終わることができた。

Capistrano-rails インストール

Gemfile に以下の様に編集します。

1
2
3
4
5
6
7
#省略
group :development do
gem "capistrano", "~> 3.12", require: false
gem 'capistrano-rbenv', '~> 2.1'
gem 'capistrano-bundler', '~> 1.6'
gem "capistrano-rails", "~> 1.4", require: false
end

bundle installで capistrano-bundler をインストール。

Capfile と deploy.rb を編集3

Capfile にてcapistrano/railsのコメントアウトを外す。

Capfile
1
2
3
# コメントアウトを外す
require "capistrano/rails/assets"
require "capistrano/rails/migrations"

config/deploy.rb を以下のように編集。
(といってもほとんどサンプルをコピペ)

config/deploy.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# config valid for current version and patch releases of Capistrano
lock "~> 3.12.1"

# デプロイ先設定
set :application, "testapp"
set :repo_url, "git@github.com:Octo8080/captest.git"

# rbenv設定
set :rbenv_type, :user
set :rbenv_ruby, '2.4.9'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} #{fetch(:rbenv_path)}/bin/rbenv exec"

# bundler設定
set :linked_dirs, fetch(:linked_dirs, []) << '.bundle'

# アプリケーションで共有するものを定義する。
# デプロイしたバージョン間で共有されることになる。
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', '.bundle', 'public/system', 'public/uploads'
append :linked_files, 'config/database.yml'

サンプルだとappend :linked_files, 'config/database.yml'の部分は次のようになっている。

1
append :linked_files, 'config/database.yml', 'config/secrets.yml'

rails5.2 からは、secrets.ymlは廃止されて、credentials.yml.encに統合されているそう。
Rails5.2 から secrets.yml*が廃止され credentials.yml.enc に統合されるよ

ただcredentials.yml.encでのsecret_key_baseの設定に失敗したので、.bashrcに環境変数で設定することにした。

.bashrc
1
export SECRET_KEY_BASE=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

一旦確認

bundle exec cap production deployを実行すると、以下のエラーになる。

1
ERROR linked file /var/www/testapp/shared/config/database.yml does not exist on xxx.xxx.xxx.xxx

/var/www/testapp/shared/config/database.ymlがない。
config/deploy.rbに定義したappend :linked_filesの項目は、自分でコピーしてあげる必要があるそう。
config/database.ymlをデプロイ先サーバーの/var/www/testapp/shared/以下に保管する。
なので、手動でコピーしてbundle exec cap production deployを実行する。

ActiveRecord::NoDatabaseError: Unknown database 'xxxxxxxxxxxxx'のエラーが発生。
デプロイ先にデータベースがないそう。デプロイ先のデータベースは手動で作りました。

ここまでやってbundle exec cap production deployを再度実行すると、エラーなく終了できる。

サーバに ssh で接続し、確認するとテーブルが作成されていることが確認できる。

capistrano-puma をインストール

Gemfile に以下の様に編集します。

1
2
3
4
5
6
7
8
#省略
group :development do
gem "capistrano", "~> 3.12", require: false
gem 'capistrano-rbenv', '~> 2.1'
gem 'capistrano-bundler', '~> 1.6'
gem "capistrano-rails", "~> 1.4", require: false
gem 'capistrano3-puma', github: "seuros/capistrano-puma"
end

bundle installで capistrano3-puma をインストール。

Capfile と deploy.rb を編集4

Capfile にてrequire 'capistrano/puma'を記述。

Capfile
1
2
3
4
require 'capistrano/puma'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Daemon
install_plugin Capistrano::Puma::Nginx

config/deploy.rb を以下のように編集。

config/deploy.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# config valid for current version and patch releases of Capistrano
lock "~> 3.12.1"

# デプロイ先設定
set :application, "testapp"
set :repo_url, "git@github.com:Octo8080/captest.git"

# rbenv設定
set :rbenv_type, :user
set :rbenv_ruby, '2.4.9'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} #{fetch(:rbenv_path)}/bin/rbenv exec"

# bundler設定
set :linked_dirs, fetch(:linked_dirs, []) << '.bundle'

# アプリケーションで共有するものを定義する。
# デプロイしたバージョン間で共有されることになる。
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', '.bundle', 'public/system', 'public/uploads'
append :linked_files, 'config/database.yml'

/puma.rb を作成

bundle exec cap production puma:configを実行すると、デプロイ先サーバーで/var/www/testapp/shared/puma.rbが作成される。

内容は以下のようになっていた。

/shared/puma.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
#!/usr/bin/env puma

directory '/var/www/testapp/current'
rackup "/var/www/testapp/current/config.ru"
environment 'production'

tag ''

pidfile "/var/www/testapp/shared/tmp/pids/puma.pid"
state_path "/var/www/testapp/shared/tmp/pids/puma.state"
stdout_redirect '/var/www/testapp/shared/log/puma_access.log', '/var/www/testapp/shared/log/puma_error.log', true

threads 0,16

bind 'unix:///var/www/testapp/shared/tmp/sockets/puma.sock'

workers 0

restart_command 'bundle exec puma'

prune_bundler

on_restart do
puts 'Refreshing Gemfile'
ENV["BUNDLE_GEMFILE"] = ""
end

一旦確認

bundle exec cap production deployを実行すると、エラーなく通ったがよくわからない。
ので、ssh でサーバーに接続してプロセスを確認する。

1
2
[root@localhost testapp]# ps aux|grep puma
root 7387 0.8 0.3 770804 112228 ? Sl 13:24 0:01 puma 4.3.3 (unix:///var/www/testapp/shared/tmp/sockets puma.sock)

とりあえず起動できているらしい。

bundle exec cap production puma:nginx_configを実行して nginx 用の設定ファイルを作ります。

実行すると、
mv: /tmp/nginx_testapp_production' から /etc/nginx/sites-available/testapp_production' へ移動できません: そのようなファイルやディレクトリはありませんというエラーが出たので、手動で作成しました。

1
2
3
mkdir /etc/nginx/sites-available
mkdir /etc/nginx/sites-available/testapp_production
mkdir /etc/nginx/sites-enabled/

bundle exec cap production puma:nginx_configを再度実行。
作成した/etc/nginx/sites-available/testapp_productionを見てみる。、
/etc/nginx/sites-available/testapp_productionへのリンクが作成されていた。

1
2
3
4
5
ls -la /etc/nginx/sites-enabled/testapp_production/
合計 0
drwxr-xr-x. 2 root root 31 3月 28 13:45 .
drwxr-xr-x. 3 root root 31 3月 28 13:45 ..
lrwxrwxrwx. 1 root root 45 3月 28 13:45 testapp_production -> /etc/nginx/sites-available/testapp_production

設定ができたので nginx を reload しておく。
nginx -s reloadを実行。
うまくいかない。

対応

実は、ここでうまくいかなかったので調査して先に 2 つ記事を書きました。

解決方法は次の 2 つでした。

  • nginx の実行ユーザーを rails の実行ユーザーと合わせる
  • /etc/nginx/sites-available/testapp_production/nginx_testapp_productionに作成された設定ファイルの修正

/etc/nginx/sites-available/testapp_production/nginx_testapp_productionの修正点は 1 つ、server_nameでした。

1
2
3
4
# 変更前
server_name localhost testapp.local;
# 変更後
server_name xxx.xxx.xxx.xxx testapp.local;

考えてみれば、localhost では IP 指定してアクセスしても合致しないので、駄目ですね。

修正してから、bundle exec cap production deployを実行し再度デプロイすることで、サーバーでの動作が確認できました。


今回は Capistrano の導入を調べながら、一通りやってみました。
Capistrano を導入すると、コマンド 1 つで、アプリケーションを更新できるのが面白いし便利なのが再確認できました。

今のところメモレベルなので、次はすべてまとめて導入する。
まとまった記事にして、置きたいところです。

ではでは。