Just do IT

思うは招く

Capistrano 超初心者がなんとなく理解するために Rails アプリではなくファイルをデプロイしてみる

初心者がCapistranoRailsアプリをデプロイするのは難しい

初心者にとって、Capistranoを使っていきなりRailsアプリのデプロイ自動化をするのは、ハードルが高い。エラーがたくさん出て、心が折れそうになる。

f:id:K_Koh:20200411095255p:plain

Capistranoのデプロイに関する記事の多くは、「デプロイが何をする行為なのかをすでに知っている人」を対象に書かれている。

前提となる知識やロジックの説明を省いており、チンプンカンプンになって「何言ってるかわかんねぇ・・・😱」と投げ出したくなる。

この記事では、初心者に向けて、「デプロイがどんなことをするのか、とりあえずなんとなーく理解する」ための手順を紹介する。 Railsアプリではなく、1つのファイルをデプロイすることで、ひとつの成功体験を得る。

f:id:K_Koh:20200411095909p:plain

この記事では、具体的には次のことをする。

  • ローカルに適当にディレクトリをつくり、適応なファイルを1つ設置する
  • Capistrano をインストールする
  • Capistrano の設定をする
  • ローカルでデプロイコマンドを打ち、リモートサーバにファイルがアップされているかどうかを確認する

「なんだ、ただのファイルをデプロイするのか」と思うことなかれ。

ファイルをデプロイするだけでも、初心者にはハマリポイントがいくつもある。それらをクリアすることで、Railsアプリのデプロイにも活かせる。

手を動かしながら当記事を読むことで、Capistrano が「基本的にどんなことをしようとしているか」を理解できると思う。

前提条件

以下の前提条件をクリアしている方を対象とする。

  • リモートサーバがある
  • ローカルからリモートサーバにSSH接続でログインできる
  • GitHubリポジトリを作れる
  • Bunlderが使える

環境

デプロイとはなんなのか

デプロイとは、プログラムを一般に公開できるよう、本番環境にプログラムを設置すること。

つまり今回の例でいうと、ローカルマシンから、リモートサーバにファイルを設置することを指す。 (「ファイルを設置する」ことだけをデプロイと呼ぶなと怒られるかもしれないが…)

f:id:K_Koh:20200411151426p:plain 今回目指すのは、

  • Capistranoのデプロイコマンドをローカルマシンで打ち、
  • CapistranoGitHubからファイルをクローンして、
  • リモートサーバに自動でデプロイされる(ローカルのファイルがリモートサーバに設置される)

という流れの実現とする。

では、さっそくやっていこう。

リモートサーバにデプロイ専用ユーザをつくる

f:id:K_Koh:20200411124815p:plain

Capistranoでデプロイをするときは、リモートサーバにデプロイ専用のユーザー(deploy)をつくるのが一般的。Railsの学習サイトで有名な「GoRails」でも採用されている方法なので、脳死で従おう。

Deploy Ruby On Rails to Ubuntu 18.04 Bionic Beaver (2019 Update) | GoRails

契約しているリモートサーバにログインして、デプロイするための専用ユーザーをつくる。 今回はリモートサーバはさくらVPSを使用し、OSにはDebianをインストールしている。

sudoグループをつくる(あれば必要なし)

※リモートサーバ
sudo visudo

Debianの場合、sudoグループは最初から存在した。他のLinuxディストリビューションではわからないが、ない場合は作成しよう。

開いたファイルに以下を追記。

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

# 一番最後の行に追記
deploy  ALL=NOPASSWD: ALL 
  • %sudo ALL=(ALL:ALL) ALL:sudoグループに入っているユーザは、どんなコマンドも実行できる権限がある
  • deploy ALL=NOPASSWD: ALL:ここに設定したユーザは、すべてのコマンドをパスワード入力なしで実行できる

deployユーザがデプロイに関していろいろ実行するとき、いちいちパスワードを入力することは不可能。よって、パスワードの入力をしなくてもコマンドを実行できるように設定する。

デプロイユーザーをつくる

リモートサーバで、deployユーザをつくる。

sudo adduser deploy # ユーザーを作成
sudo adduser deploy sudo # sudoグループに追加

これで、deployユーザをsudoグループに含めることができた。

f:id:K_Koh:20200411130951p:plain

当記事では今後、deployユーザでリモートサーバにログインする。

deployユーザでローカルからログインする場合のコマンドはつぎのとおり。

# ポート番号を指定しない場合
ssh deploy@IPアドレス

# ポート番号を指定する場合
ssh -p ポート番号 deploy@IPアドレス

参考:SSHサーバーにログインするには? sshコマンド:ネットワーク管理の基本Tips - @IT

/var/www があるか確認する

Capistranoでデプロイした場合、デフォルトでは/var/wwwにアプリやファイルがアップされる。

/var/www

Debianだとこのディレクトリはデフォルトで存在する。もしこのディレクトリがなければ、リモートサーバで作成しておく。

mkdir /var/www

適当なディレクトリをつくる

ローカルPCに戻り、デプロイするための適当なディレクトリをつくろう。

mkdir cap_test
cd cap_test

今回デプロイするための、適当なファイルをつくる。

touch test-file 

Githubリポジトリをつくる

※ローカルPC

いまつくったディレクトリを、GitHubに登録しよう。

github.com

git init
echo "# はじめてのCapistrano" > README.md
git add .
git commit -m "first commit"

# ここでGitHubリポジトリ作成しておく

git remote add origin git@github.com:GitHubユーザーネーム/リポジトリ名.git
git push -u origin master

GitHubリポジトリの作り方は次の記事で紹介している。

git init から git push までの流れ - オランウータンとぼく

リモートサーバに公開鍵を設置

※リモートサーバ

# リモートサーバでdeployユーザでログイン
sudo su - deploy

# 公開鍵を設置するディレクトリを作成
mkdir .ssh

# ローカルの公開鍵を以下ファイルにコピーする
vim ~/.ssh/authorized_keys 

# 権限を設定
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

ssh-agentの設定

※ローカルPC

Capistranoが動くと、リモートサーバ → GitHubへクローンのリクエストをする。その際に、リモートサーバからGitHubSSH接続が発生する。 それができるように、自分の鍵ファイルを次のようにssh-addする。

ssh-add ~/.ssh/id_rsa

必要なgemをインストール

※ローカルPC

まずはbundle initする。

bundle init

作成されたGemfileに追記。

gem 'capistrano'
gem 'capistrano-safe-deploy-to'

Railsアプリではないので、今回はdevelopementグループ内には書かなくていい。(そもそもないはず)

そしてbundle install

bundle install

Capistrano の設定ファイルを作成

※ローカルPC

以下のコマンドでCapistranoの設定ファイルを作成できる。

bundle exec cap install

# 結果
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

それぞれの使い方

  • Capfile: Capistranoに関する設定
  • deploy.rb: 基本設定
  • staging.rb: ステージング環境に関する設定
  • production.rb: production環境に関する設定

Capfile

※ローカルPC

Capistranoフレームワークであり、いろんなプラグインも併用して設定していく。 そのため、Capfileには、require 'プラグイン名'を書いたりする。

今回はこう書く。 ※もともと書いてある記述は削除してOK

Capfile

require "capistrano/setup"
require "capistrano/deploy"
require "capistrano/safe_deploy_to"
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

※ローカルPC

config/deploy.rb は次のように書く。

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

# アプリ名
set :application, 'cap_test'

# GitHubのリポジトリ名
set :repo_url, 'git@github.com:GitHubのユーザーネーム/cap_test.git'
  • lock〜の部分はもともと書いてあったバージョンのまま残す
  • アプリ名は自分がわかりやすいものならなんでもよく、GitHubにアップしているアプリ名と合わせる必要はない
  • リポジトリ名はGitHubで確認できる

config/deploy/production.rb

※ローカルPC

config/deploy/production.rb も、デフォルトの記述はすべて消して以下を追記。

server "リモートサーバのIPアドレス", user: "deploy", roles: %w{web db app}

# ssh
set :ssh_options, {
  user: "deploy",
  port: ポート番号,
  keys: %w(~/.ssh/id_rsa),
  forward_agent: true,
  auth_methods: %w[publickey]
}
  • serverにはリモートサーバに割り当てられたIPアドレスをいれる
  • ポート番号の基本は22だと思うが、変更している場合は記入する
  • ~/.ssh/id_rsaの部分は、鍵ファイルへのパスを書く。読者のファイルパス名が違えば、書き換えが必要になる

このsshの設定で、リモートサーバ → GitHub へクローンのリクエストが送れるようになる。

GitHubへpush

デプロイする前にGitHubへpushしておく。

git add .
git commit -m "second commit"
git push origin master

これで準備が整った。ついにデプロイしてみよう・・・!

ついにデプロイ

※ローカルPC

cap_testディレクトリにいることを確認して、以下を実行。

bundle exec cap production deploy

こんな表示がズラーっと流れていくはず。

$ bundle exec cap production deploy
00:00 safe_deploy_to:create
      01 sudo mkdir -pv /var/www/cap_test
    ✔ 01 deploy@IPアドレス 0.610s
00:00 safe_deploy_to:ensure_owner
      01 sudo chown deploy:deploy /var/www/cap_test
    ✔ 01 deploy@IPアドレス 0.080s
00:00 git:wrapper
      01 mkdir -p /tmp
    ✔ 01 deploy@IPアドレス 0.081s
      Uploading /tmp/git-ssh-cap_test-production-kotakanazawa.sh 100.0%
      02 chmod 700 /tmp/git-ssh-cap_test-production-kotakanazawa.sh
    ✔ 02 deploy@IPアドレス 0.070s
~
~
~

リモートサーバで確認

リモートサーバにログインし、Capistranoがファイルをアップしてくれたか確認する。

$ cd /var/www
$ ls
cap_test # できていれば完成!

ディレクトリ構造の変化を確認しよう

Capistranoでデプロイをすると、アプリのディレクトリ構成が変わるので見ておこう。

~/var/www/cap_test$ ls
current  releases  repo  revisions.log  shared

ローカルと比べて、かなり変わっていることに気づくはず。

treeコマンドで見てみるとわかりやすい。 (treeコマンドがない場合はsudo apt-get install treeなど)

~/var/www/cap_test$  tree
.
|-- current -> /var/www/cap_test/releases/20200405013344
|-- releases
|   |-- 20200405001121
|   |   |-- Capfile
|   |   |-- config
|   |   |   |-- deploy
|   |   |   |   |-- production.rb
|   |   |   |   `-- staging.rb
|   |   |   `-- deploy.rb
|   |   |-- Gemfile
|   |   |-- Gemfile.lock
|   |   |-- log
|   |   |   `-- capistrano.log
|   |   |-- README.md
|   |   |-- REVISION
|   |   `-- test_file
|   |-- 20200405003916
|   |   |-- Capfile
|   |   |-- config
|   |   |   |-- deploy
|   |   |   |   |-- production.rb
|   |   |   |   `-- staging.rb
|   |   |   `-- deploy.rb
|   |   |-- Gemfile
|   |   |-- Gemfile.lock
|   |   |-- log
|   |   |   `-- capistrano.log
|   |   |-- README.md
|   |   |-- REVISION
|   |   `-- test_file
|   `-- 20200405013344
|       |-- Capfile
|       |-- config
|       |   |-- deploy
|       |   |   |-- production.rb
|       |   |   `-- staging.rb
|       |   `-- deploy.rb
|       |-- Gemfile
|       |-- Gemfile.lock
|       |-- log
|       |   `-- capistrano.log
|       |-- README.md
|       |-- REVISION
|       `-- test_file
~
~
~

という感じで、ディレクトリが大きく変わることを確認できた。

これであなたも、Capistranoでのデプロイがなんとなーく理解できたら幸いです。

f:id:K_Koh:20200411095909p:plain

デプロイがどうしてもできない場合

この記事を見て、デプロイができなかった場合はコメントをください。私も未熟なので解決策を教えられるかはわかりませんが、一緒に考えることはできます。

参考