• 技術が集うTECH GUILD

    概要

    Capistranoというデプロイツールを知りました。処理をrubyで書いて拡張できます。Vueアプリのデプロイに利用したので、そのときのメモを記します。

    作成したタスクは以下の処理を行うように作りました。

    1. SSHでサーバにログイン
    2. Bitbucketからソースを取得
    3. yarnでbuild
    4. 不要ファイル削除
    5. Webサーバの公開ディレクトリにシンボリックリンクを貼る(ブラウザで閲覧できるよう公開する)

    このうち、1、2、5、はCapistranoが備える機能で実現でき、3、4をスクリプトとして追加しました。

    詳細

    Capistranoの準備

    今回はVueアプリを配備するが、アプリの内容はJavaScriptでもRailsアプリなんでも良いです。

    bundleを使います。

    $ bundle init
    Writing new Gemfile to /Users/user/appname/Gemfile

    bundleでcapistranoをインストールします。

    $ bundle add capistrano
    Fetching gem metadata from https://rubygems.org/……….
    Resolving dependencies…
    Fetching gem metadata from https://rubygems.org/……….
    Resolving dependencies…
    Using rake 12.3.2
    Using net-ssh 5.1.0
    Using net-scp 1.2.1
    Using sshkit 1.18.2
    Using airbrussh 1.3.1
    Using bundler 1.17.2
    Using concurrent-ruby 1.1.4
    Using i18n 1.5.3
    Using capistrano 3.11.0

    アプリのディレクトリ(Vueであればvue initしたディレクトリ、ここでは/Users/user/appname)で以下を実行します。

    $ 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

    基本的な設定

    書き換えるファイルは大きく3点

    • {アプリフォルダ]/Capfile
    • {アプリフォルダ}/config/deploy.rb
    • {アプリフォルダ}/config/deploy/production.rb|staging.rb

    {アプリフォルダ}はcap installを実行したフォルダです。ここでは/Users/user/appnameです。
    production.rbとstaging.rbがあり、環境による切り分けが可能ですが、とりあえず試すのであれば、production.rbに書いてしまえば良いです。

    ファイルの説明

    • Capfile – Capistrano全体の設定などを記述する
    • deploy.rb – デプロイで共通する処理を記述する
    • production.rbなど – SSH接続などの環境ごとに異なる設定を記述する

    設定変更

    Capfile

    # require "capistrano/rvm"
    require "capistrano/rbenv"
    # require "capistrano/chruby"
    # require "capistrano/bundler"
    # require "capistrano/rails/assets"
    # require "capistrano/rails/migrations"
    # require "capistrano/passenger"

    rbenvを使用しているため、コメントをはずしました。

    production.rb

    role :web, %w{user@xxx.xxx.xxx.xxx}
    set :assets_roles, [:web]
    server 'xxx.xxx.xxx.xxx', user: 'user', roles: %w{web}
    set :ssh_options, {
    port: 22,
    keys: %w(~/.ssh/user.pem),
    forward_agent: true,
    }

    ここではSSH接続の設定のため、接続先サーバのIPアドレス、及びユーザを指定します。keysのところは、パスワード認証ではなく秘密鍵認証としたため、秘密鍵の格納場所を指定しました。

    deploy.rb

     lock "~> 3.11.0"
    set :rbenv_ruby, "2.5.1"
    set :application, "appname"
    set :branch, "master"
    set :repo_url, "git@bitbucket.org:apps/#{fetch(:application)}.git"
    set :deploy_to, "/var/www/#{fetch(:application)}"
    set :keep_releases, 6

    desc 'yarn build'
    after 'deploy:updated', :build do
    on roles :web do
    within release_path do
    execute :yarn
    execute :yarn, 'build'
    end
    end
    end

    desc 'rm except dist dir' # ., .., dist以外を削除する
    after 'deploy:updated', :rm do
    on roles :web do
    within release_path do
    execute :ls, '-a|egrep -v \'^(.|..|dist)$\'|xargs rm -r'
    end
    end
    end

    この処理では、1つ目がyarn;yarn buildを、2つ目がdistディレクトリ以外の削除を行なっています。
    repo_urlを設定することによってgitからソースを取得しています。
    keep-releaseを設定することにより世代管理されます。最新アプリのディレクトリはcurrentとなり、実体はreleaseディレクトリ配下に世代管理されています。

    SSH接続の準備

    鍵ペアを2つ生成し、1つはサーバ接続用として、~/.ssh/配下に秘密鍵を格納し、接続先サーバに公開鍵を格納しました。
    2つめは、~/.ssh/配下に秘密鍵を格納し、gitリポジトリに公開鍵を格納しました。

    capistranoから鍵を使用するため、ssh-addで秘密鍵を追加します。

    $ ssh-add ~/.ssh/repo_rsa
    $ ssh-add ~/.ssh/appname_rsa
    Identity added: /Users/user/.ssh/appname_rsa (/Users/user/.ssh/appname_rsa)

    公開ディレクトリの設定

    nginxの公開ディレクトリの設定を/var/www/appname/current/distとしました。
    これにより、yarn buildされた結果がdistに含まれた状態でcurrent->release/2019xxxxxxxxxxを参照するようシンボリックリンクが貼られることで、参照可能になります。

    実行

    $ cap production deploy 
    00:00 git:wrapper
    01 mkdir -p /tmp
    ✔ 01 user@XXX.XXX.XXX.XXX 0.069s
    Uploading /tmp/git-ssh-appname-production-user.sh 100.0%
    02 chmod 700 /tmp/git-ssh-appname-production-user.sh
    ✔ 02 user@XXX.XXX.XXX.XXX 0.078s
    00:00 git:check
    01 git ls-remote git@bitbucket.org:apps/appname.git HEAD
    01 6fd3e4ccf1b29b3d2e8fc680a1f5eac5d3XXXXXX HEAD
    ✔ 01 user@XXX.XXX.XXX.XXX

    〜〜省略〜〜

    00:06 build
    01 yarn
    01 yarn install v1.13.0
    01 [1/4] Resolving packages…
    01 [2/4] Fetching packages…
    01 info fsevents@1.2.7: The platform "linux" is incompatible with this module.
    01 info "fsevents@1.2.7" is an optional dependency and failed compatibility check. Excluding it from installation.
    01 [3/4] Linking dependencies…
    01 [4/4] Building fresh packages…
    01 Done in 13.69s.
    ✔ 01 appname@XXX.XXX.XXX.XXX 14.091s
    02 yarn build
    02 yarn run v1.13.0
    02 $ vue-cli-service build
    02
    02 - Building for production…

    〜〜省略〜〜

    01:05 rm
    01 ls -a|egrep -v '^(.|..|dist)$'|xargs rm -r
    ✔ 01 user@XXX.XXX.XXX.XXX 1.006s
    01:06 deploy:symlink:release
    01 ln -s /var/www/appname/releases/20190224174918 /var/www/appname/releases/current
    ✔ 01 appname@XXX.XXX.XXX.XXX 0.065s
    02 mv /var/www/appname/releases/current /var/www/appname
    ✔ 02 appname@XXX.XXX.XXX.XXX 0.076s

    まとめ

    capistranoを使用して、Webサーバにデプロイするタスクを作成しました。

    どうもcapistrano-yarnというものがあるようで、こちらは公式にyarnをサポートしているようです。機会があれば導入してみようと思います。

    参考

    capistrano -GitHub
    https://github.com/capistrano/capistrano/blob/master/README.md


    コメントを残す

    このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください