kumilog.net

データ分析やプログラミングの話などを書いています。

Capistranoでデプロイ自動化

はじめに

Capistranoは、サーバへのデプロイを自動化するオープンソースソフトウェアです。 Rubyで書かれており、Railsアプリケーションのデプロイによく用いられますが、Rails以外でも使うことができます。 今回はアプリケーションの種類を限定せずGitHubなどからソースを持ってきてデプロイすることを考えてみます。

サーバ側での作業

まずはじめにデプロイするサーバの準備を行います。 Ubuntu 18.04 を用いましたが、他のOSでも大丈夫だと思います。

デプロイ用のユーザの作成

デプロイ用のユーザdeployを作成します。

$ sudo adduser deploy
$ sudo gpasswd -a deploy sudo

ローカルからsshログインできるように公開鍵の登録をしておきます。

$ sudo su - deploy
$ mkdir ~/.ssh
$ echo 'ssh-rsa xxx' >> ~/.ssh/authorized_keys
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys

以降、サーバ側の作業は、deployユーザで行います。

アプリケーションディレクトリの作成

アプリケーションを格納するディレクトリを用意しておきます。 Webアプリケーションを想定して/var/www/にしていますが、場所はどこでも良いです。

$ sudo mkdir -p /var/www/myapp
$ sudo chown deploy:deploy /var/www/myapp

アプリケーション名はmyappとしていますが、適宜修正してください。 以降も、アプリケーション名はmyappとなっています。

(任意)Githubへの公開鍵の登録

GithubやGitLabのプライベートリポジトリにあるアプリケーションをデプロイする場合は、このサーバからリポジトリへアクセスできるように公開鍵をGithubなどに登録しておきます。

ローカル側での作業

デプロイを実行するローカルの準備をしていきます。 なお、Rubyがインストールされている必要があります。今回用いたバージョンは2.5.1です。

デプロイ用のディレクトリの作成

Capistranoをインストールするディレクトリを作成します。

$ mkdir myapp-deploy
$ cd myapp-deploy

bundle initを行うと、Gemfileが生成されます。

$ bundle init

Capistranoのインストール

Gemfileに以下を加筆します。

gem 'capistrano', '~> 3.11', require: false

bundle installでインストールを行うと、Capistranoと依存関係にあるGemが指定したパス./vendor/bundleにインストールされます。

$ bundle install --path ./vendor/bundle

以下のコマンドで、Capfileの他いくつかのファイルが生成されます。

$ bundle exec cap install

Capistranoの設定

config/deploy.rb がデプロイの共通設定ファイルになります。以下のように記載します。

# アプリケーション名
set :application, "myapp"

# GtiリポジトリのURL
set :repo_url, "git@github.com:me/myapp.git"

# デプロイするブランチ(デフォルトはmasterブランチ)
set :branch, master

# デプロイ先のディレクトリ
set :deploy_to, "/var/www/myapp"

config/deploy/に環境ごとの設定ファイルが入っています。 今回はprodctionのみ設定してみます。config/deploy/prodction.rbに以下のように記載します。

# サーバのホスト名とユーザ名
server "example.com", user: "deploy", roles: %w{app}

# SSHの設定
set :ssh_options, {
  keys: %w(~/.ssh/id_rsa),
  forward_agent: true,
  auth_methods: %w(publickey)
}

デプロイ実行

設定が完了したので、いよいよデプロイの実行です。

その前にドライランを行うとどのような処理が実行されるか確認できます。

$ bundle exec cap production deploy --dry-run
00:00 git:wrapper
      01 mkdir -p /tmp
      02 #<StringIO:0x00007fc227afc648> /tmp/git-ssh-myapp-production-username.sh
      03 chmod 700 /tmp/git-ssh-myapp-production-username.sh
00:00 git:check
      01 git ls-remote git@gitlab.com:me/myapp.git HEAD
00:00 deploy:check:directories
      01 mkdir -p /var/www/myapp/shared /var/www/myapp/releases
00:00 git:clone
      The repository mirror is at /var/www/myapp/repo
00:00 git:update
      01 git remote set-url origin git@gitlab.com:me/myapp.git
      02 git remote update --prune
00:00 git:create_release
      01 mkdir -p /var/www/myapp/releases/20181128130637
      02 git archive master | /usr/bin/env tar -x -f - -C /var/www/myapp/releases/20181128130637
00:00 deploy:set_current_revision
      01 echo "" > REVISION
00:00 deploy:symlink:release
      01 ln -s /var/www/myapp/releases/20181128130637 /var/www/myapp/releases/current
      02 mv /var/www/myapp/releases/current /var/www/myapp
00:00 deploy:log_revision
      01 echo "Branch master (at ) deployed as release 20181128130637 by username" >> /var/www/myapp/revisions.log

問題なければ、実際にデプロイしてみます。

$ bundle exec cap production deploy

/var/www/myapp/releases/20180930060858 のようなフォルダにGitからクローンされ、最新版が/var/www/myapp/currentにシンボリックリンクが貼られます。

共通ファイルとフォルダの設定

設定ファイルやログのようにgitで管理しないファイルやフォルダについては、共通フォルダに格納しておいたほうが都合が良いです。

config/deploy.rbに設定するファイルやフォルダを以下のように記載します。

# 共通ファイル
append :linked_files, "config.yml"

# 共通フォルダ
append :linked_dirs, "log"

改めてデプロイすると、/var/www/myapp/currentから/var/www/myapp/shared/へシンボリックリンクが貼られます。

トラブルシューティング

SSH接続できない

最初のタスクのgit:wrapperで以下のようなエラーが発生する場合、ローカルからサーバへSSH接続ができていないです。

SSHKit::Runner::ExecuteError: Exception while executing as deploy@example.com: Authentication failed for user deploy@example.com

Capistranoを使わずに普通にSSHできるか確かめてみます。

ssh deploy@example.com

sshコマンドで接続できる場合、config/deploy/prodction.rbのSSH設定が誤っていると思われます。鍵の場所なども確認しましょう。

Gitクローンできない

git:checkSSHKit::Runner::ExecuteErrorが発生する場合、サーバ側からGitリポジトリへアクセスできていない可能性があります。 これはプライベートリポジトリの場合のみ発生すると思いますが、サーバの鍵がGitリポジトリのあるサーバに登録されていないと思われます。

まとめ

Capistranoを用いたデプロイの方法について説明しました。Capistranoには周辺ライブラリもいくつかあり、次回はそれらを用いてRailsアプリケーションのデプロイについてお話したいと思います。