Deployment with Capistrano

38
Deployment × Capistrano 張旭 @zx1986
  • Upload

    -
  • Category

    Software

  • view

    257
  • download

    0

Transcript of Deployment with Capistrano

Page 1: Deployment with Capistrano

Deployment × Capistrano

張旭 @zx1986

Page 2: Deployment with Capistrano

部署是什麽?Deployment ?

Page 3: Deployment with Capistrano

簡單說,部署就是將您開發的程式,傳送到指定環境,並視需求進行參數設定,使其提供服務。

Page 4: Deployment with Capistrano

更簡單地說,部署就是將程式更新到指定環境。

Page 5: Deployment with Capistrano

比較傳統的部署手法:

1. 在本機開發,修改程式檔案。

2. 透過 FTP 軟體將修改過的檔案上傳到伺服器。

3. 視需求修改伺服器上的設定檔。

4. 視需要重啟服務以載入新的設定值。

Page 6: Deployment with Capistrano

比較傳統的部署手法 (劣勢):

● 檔案數量多時,上傳容易遺漏

● 沒有版本變動與發佈記錄

● 沒有快速的回復 (Rollback) 機制

● 手動修改或重載,繁瑣易出錯

● 主機數量增加時,重複工作與出錯率都倍增

Page 7: Deployment with Capistrano

簡單地使用 Git 的部署手法:

1. 在本機開發,修改程式檔案。

2. 執行 git push 遞交變更。

3. 登入伺服器,在專案目錄執行 git pull 更新。

4. 視需求修改伺服器上的設定檔。

5. 視需要重啟服務以載入新的設定值。

Page 8: Deployment with Capistrano

簡單地使用 Git 的部署手法 (劣勢):

● .git 目錄有曝露的風險

● Git Repository 的金鑰管理

● 手動修改或重載,繁瑣易出錯

● 主機數量增加時,重複工作與出錯率都倍增

Page 9: Deployment with Capistrano

當專案變複雜,使用了各種工具跟框架,部署時就會出現各種花式指令跟後續任務 (post-deploy tasks) ...

Page 10: Deployment with Capistrano

EXAMPLE

Rails- rake db:migrate RAILS_ENV=development- rake assets:precompile RAILS_ENV=production- touch tmp/restart.txt

Yii 2- composer install- yii migrate

CodeIgniter- composer install - gulp TASK_NAME

Page 11: Deployment with Capistrano

假設有 N 個後續任務,有 M 臺主機,那麽就需要執行 N×M 次動作 ...

Page 12: Deployment with Capistrano

假設有不同的主機角色,例如 App,Web,Database;不同類型的主機部署動作存在差異 ...

Page 13: Deployment with Capistrano

出錯了,所有主機要還原 ...

Page 14: Deployment with Capistrano
Page 15: Deployment with Capistrano

CapistranoA deployment tool written in Ruby

Page 16: Deployment with Capistrano

只要有 Ruby 環境 (使用 RubyGems) 就可以安裝 Capistrano,它通常安裝在您的開發主機 (PC 或 Laptop) 上。

Page 17: Deployment with Capistrano

Ruby, RubyGems, rbenv

Ruby 是一款程式語言,演進相當快速,版本眾多。

RubyGems 是套件管理工具,管理 Ruby 語言開發的套件。- 如同 npm 之於 NodeJS- 如同 Pip 之於 Python- 如同 Composer 之於 PHP

rbenv 則是管理不同版本的 Ruby 的工具,顧名思義。- 如同 nvm 之於 NodeJS- 如同 virtualenv 之於 Python- 如同 phpbrew 之於 PHP

Page 18: Deployment with Capistrano

檢查主機是否已經有 Ruby 環境

$ which ruby # 檢查是否已安裝 Ruby

$ which gem # 檢查是否已安裝 RubyGems 套件管理工具

Page 19: Deployment with Capistrano

Mac 主機安裝與設定 Ruby 環境

$ brew update

$ brew install rbenv ruby-build

$ rbenv install 2.3.0

$ rbenv global 2.3.0

$ rbenv rehash

Page 20: Deployment with Capistrano

Ubuntu 主機安裝與設定 Ruby 環境

$ sudo apt-get update

# 參考 https://github.com/sstephenson/rbenv#installation

https://github.com/sstephenson/ruby-build#readme

$ rbenv install 2.3.0

$ rbenv global 2.3.0

$ rbenv rehash

Page 21: Deployment with Capistrano

❖ Tips

1. 執行 gem install 之前,先編輯 ~/.gemrc 寫入:

install: --no-rdoc --no-ri

update: --no-rdoc --no-ri

2. 安裝新的 gem 之後,執行 rbenv rehash 重新載入。

Page 22: Deployment with Capistrano

使用 RubyGems 安裝 Capistrano

$ gem install capistrano # 安裝 Capistrano 主程式

$ gem install capistrano-hipchat # 安裝 Capistrano HipChat 外掛

$ gem install capistrano-composer

$ gem install capistrano-rails

$ gem install capistrano-ssh-doctor

$ gem install capistrano-db-tasks

Page 23: Deployment with Capistrano

Capistrano 程式在本機運行。實際上,它只是根據您的設定,遵循既有的流程,登入指定的主機 (們),執行一系列的 Shell 指令,以達成目的。

Page 24: Deployment with Capistrano

Capistrano 運作時預設會顯示執行的指令及其輸出,類似這樣:

Page 25: Deployment with Capistrano

初始化 Capistrano

$ cd my_project

$ cap install # 初始化 Capistrano 環境建立必要的設定檔

$ cap --tasks # 顯示目前可以執行的 Capistrano 任務

$ cap --help # 顯示基本的使用方法

$ git status # 偷看一下多出了哪些檔案

Page 26: Deployment with Capistrano

Capistrano 設定檔 (1)

├── Capfile└── config/ ├── deploy.rb └── deploy/ ├── production.rb └── staging.rbhttp://capistranorb.com/documentation/getting-started/configuration/

Page 27: Deployment with Capistrano

Capistrano 設定檔 (2)

● Capfile 是基礎設施宣告,宣告要引用的外掛、自訂任務等。

● deploy.rb 是一個全域的變數設定檔,裡面的設定會被各個 Stage 引用。

● Stage 指不同的部署環境,各別對應到 config/deploy/stage_name.rb,例如 staging.rb 跟 production.rb。

● Stage 是可以自訂或更名的,例如 staging.rb 可以改成 dev.rb。

Page 28: Deployment with Capistrano

Capfile

# 初始化程式

require 'capistrano/setup'

# 載入預設的部署流程

require 'capistrano/deploy'

# 載入其他外掛

require 'capistrano/hipchat'

# 從 lib/capistrano/tasks 載入其他自定義的任務

Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

Page 29: Deployment with Capistrano

deploy.rb (1)

# 限定 Capistrano 的版本

lock '3.4.0'set :application, 'my_app_name'

# 設定版本控制工具以及專案的 Git 程式庫路徑,注意遠端主機對程式庫的讀取權限問題

set :scm, :gitset :repo_url, '[email protected]:me/my_repo.git'

# 設定部署到遠端主機的目錄,使用絕對路徑,做為程式部署時的根目錄

set :deploy_to, '/path/to/project/directory/'

# 利用 ask 函式,搭配 git 指令抓取當前所在的 branch 做為要部署的版本

ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp

Page 30: Deployment with Capistrano

deploy.rb (2)

# 將要共享的檔案或目錄分別添加到 :linked_files 跟 :linked_dirs 變數中

# 多個檔案或目錄可以用逗號 (,) 區隔

# 注意!路徑是相對路徑,用以在 current 目錄底下建立 symbolic link# 真正的檔案或目錄需要使用者實際手動在 shared 目錄下建立 (後面會提到)set :linked_files, fetch(:linked_files, []).push('path/to/file')set :linked_dirs, fetch(:linked_dirs, []).push('path/to/directory')

# 定義 Capistrano 在遠端主機內運作時的環境變數

set :default_env, { MY_VAR1: "my_value1", MY_VAR2: "my_value2" }

# 需要保留的舊版本數量,預設是 5set :keep_releases, 2

Page 31: Deployment with Capistrano

deploy.rb (3)

# 在預設的部署流程中添加自訂的任務

namespace :deploy do

desc 'description of my_task' task :my_task do # roles 是所要部署的主機角色,通常定義在 stage_name.rb 中 on roles(:role_name) do # do something end end

after 'deploy:finished', 'deploy:my_task'end

Page 32: Deployment with Capistrano

staging.rb 與 production.rb

# 通常會在 stage_name.rb 中設定不同的目標主機與登入資訊

# staging.rbserver 'dev.server.my', user: 'deploy', roles: %w{app web}, port: 22

# production.rbserver 'prod1.server.my', user: 'admin', roles: %w{web}, port: 8022server 'prod2.server.my', user: 'admin', roles: %w{app}, port: 8022

# 所有在 deploy.rb 中的設定,都可以在這裡覆寫或擴充,

# 但任務 (Tasks) 的覆寫需要使用 .clear_actions 函數,請參考:

http://capistranorb.com/documentation/advanced-features/overriding-capistrano-tasks/

Page 33: Deployment with Capistrano

編寫 Capistrano 的 Tasks

編寫在遠端主機執行的任務:

http://capistranorb.com/documentation/getting-started/tasks/

編寫在本機執行的任務:

http://capistranorb.com/documentation/getting-started/local-tasks/

Page 34: Deployment with Capistrano

Capistrano 部署出去的目錄結構 (1)

├─ current -> /path/to/project/directory/releases/20150908300022/├─ releases/│ ├── 20150807250011/ # {YYYYMMDDhhmmss}│ ├── 20150903080022/├─ repo/│ └── <版本控制軟體的原始檔案>├─ revisions.log└─ shared/ └── <linked_files 跟 linked_dirs 實際存放的地方>

Page 35: Deployment with Capistrano

Capistrano 部署出去的目錄結構 (2)

● current 是一個 symbolic link,指向 releases 內的當前發佈目錄。

● releases 存放每次部署所產生的目錄,其源自於 repo。

● repo 是一個 Bare Git Repository,部署時使用 git archive 指令,從裡面取

出檔案放到 releases 目錄之下。

● revisions.log 是一個版本記錄檔,記錄每次部署所對應的 git hash。

● shared 存放共享的檔案跟目錄,如果有設定,在每個 releases 內的目錄都會

有 symbolic link 指向 shared 內的檔案或目錄。最常見的就是 config 檔、

upload 目錄、tmp 目錄、cache 目錄等。

Page 36: Deployment with Capistrano

執行 Capistrano 部署與還原

$ cap staging deploy

$ cap staging deploy:rollback

$ cap production deploy

$ cap production deploy:rollback

# rollback 實際上是將 current 指向 releases 底下前一版的目錄而已,非常快速。

Page 37: Deployment with Capistrano

Back to the storySomeone else’s Story ...

https://speakerdeck.com/aleiphoenix/automate-deploying-using-capistrano

Page 38: Deployment with Capistrano

cap wherever deploy