Slide 1

Slide 1 text

Deployment × Capistrano 張旭 @zx1986

Slide 2

Slide 2 text

部署是什麽? Deployment ?

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

比較傳統的部署手法: 1. 在本機開發,修改程式檔案。 2. 透過 FTP 軟體將修改過的檔案上傳到伺服器。 3. 視需求修改伺服器上的設定檔。 4. 視需要重啟服務以載入新的設定值。

Slide 6

Slide 6 text

比較傳統的部署手法 (劣勢): ● 檔案數量多時,上傳容易遺漏 ● 沒有版本變動與發佈記錄 ● 沒有快速的回復 (Rollback) 機制 ● 手動修改或重載,繁瑣易出錯 ● 主機數量增加時,重複工作與出錯率都倍增

Slide 7

Slide 7 text

簡單地使用 Git 的部署手法: 1. 在本機開發,修改程式檔案。 2. 執行 git push 遞交變更。 3. 登入伺服器,在專案目錄執行 git pull 更新。 4. 視需求修改伺服器上的設定檔。 5. 視需要重啟服務以載入新的設定值。

Slide 8

Slide 8 text

簡單地使用 Git 的部署手法 (劣勢): ● .git 目錄有曝露的風險 ● Git Repository 的金鑰管理 ● 手動修改或重載,繁瑣易出錯 ● 主機數量增加時,重複工作與出錯率都倍增

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

Capistrano A deployment tool written in Ruby

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

Ruby, RubyGems, rbenv Ruby 是一款程式語言,演進相當快速,版本眾多。 RubyGems 是套件管理工具,管理 Ruby 語言開發的套件。 - 如同 npm 之於 NodeJS - 如同 Pip 之於 Python - 如同 Composer 之於 PHP rbenv 則是管理不同版本的 Ruby 的工具,顧名思義。 - 如同 nvm 之於 NodeJS - 如同 virtualenv 之於 Python - 如同 phpbrew 之於 PHP

Slide 18

Slide 18 text

檢查主機是否已經有 Ruby 環境 $ which ruby # 檢查是否已安裝 Ruby $ which gem # 檢查是否已安裝 RubyGems 套件管理工具

Slide 19

Slide 19 text

Mac 主機安裝與設定 Ruby 環境 $ brew update $ brew install rbenv ruby-build $ rbenv install 2.3.0 $ rbenv global 2.3.0 $ rbenv rehash

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

❖ Tips 1. 執行 gem install 之前,先編輯 ~/.gemrc 寫入: install: --no-rdoc --no-ri update: --no-rdoc --no-ri 2. 安裝新的 gem 之後,執行 rbenv rehash 重新載入。

Slide 22

Slide 22 text

使用 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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

初始化 Capistrano $ cd my_project $ cap install # 初始化 Capistrano 環境建立必要的設定檔 $ cap --tasks # 顯示目前可以執行的 Capistrano 任務 $ cap --help # 顯示基本的使用方法 $ git status # 偷看一下多出了哪些檔案

Slide 26

Slide 26 text

Capistrano 設定檔 (1) ├── Capfile └── config/ ├── deploy.rb └── deploy/ ├── production.rb └── staging.rb http://capistranorb.com/documentation/getting-started/configuration/

Slide 27

Slide 27 text

Capistrano 設定檔 (2) ● Capfile 是基礎設施宣告,宣告要引用的外掛、自訂任務等。 ● deploy.rb 是一個全域的變數設定檔,裡面的設定會被各個 Stage 引用。 ● Stage 指不同的部署環境,各別對應到 config/deploy/stage_name.rb, 例如 staging.rb 跟 production.rb。 ● Stage 是可以自訂或更名的,例如 staging.rb 可以改成 dev.rb。

Slide 28

Slide 28 text

Capfile # 初始化程式 require 'capistrano/setup' # 載入預設的部署流程 require 'capistrano/deploy' # 載入其他外掛 require 'capistrano/hipchat' # 從 lib/capistrano/tasks 載入其他自定義的任務 Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

Slide 29

Slide 29 text

deploy.rb (1) # 限定 Capistrano 的版本 lock '3.4.0' set :application, 'my_app_name' # 設定版本控制工具以及專案的 Git 程式庫路徑,注意遠端主機對程式庫的讀取權限問題 set :scm, :git set :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

Slide 30

Slide 30 text

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" } # 需要保留的舊版本數量,預設是 5 set :keep_releases, 2

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

staging.rb 與 production.rb # 通常會在 stage_name.rb 中設定不同的目標主機與登入資訊 # staging.rb server 'dev.server.my', user: 'deploy', roles: %w{app web}, port: 22 # production.rb server 'prod1.server.my', user: 'admin', roles: %w{web}, port: 8022 server 'prod2.server.my', user: 'admin', roles: %w{app}, port: 8022 # 所有在 deploy.rb 中的設定,都可以在這裡覆寫或擴充, # 但任務 (Tasks) 的覆寫需要使用 .clear_actions 函數,請參考: http://capistranorb.com/documentation/advanced-features/overriding-capistrano-tasks/

Slide 33

Slide 33 text

編寫 Capistrano 的 Tasks 編寫在遠端主機執行的任務: http://capistranorb.com/documentation/getting-started/tasks/ 編寫在本機執行的任務: http://capistranorb.com/documentation/getting-started/local- tasks/

Slide 34

Slide 34 text

Capistrano 部署出去的目錄結構 (1) ├─ current -> /path/to/project/directory/releases/20150908300022/ ├─ releases/ │ ├── 20150807250011/ # {YYYYMMDDhhmmss} │ ├── 20150903080022/ ├─ repo/ │ └── <版本控制軟體的原始檔案> ├─ revisions.log └─ shared/ └──

Slide 35

Slide 35 text

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 目錄等。

Slide 36

Slide 36 text

執行 Capistrano 部署與還原 $ cap staging deploy $ cap staging deploy:rollback $ cap production deploy $ cap production deploy:rollback # rollback 實際上是將 current 指向 releases 底下前一版的目錄而已,非常快速。

Slide 37

Slide 37 text

Back to the story Someone else’s Story ... https://speakerdeck.com/aleiphoenix/automate-deploying-using-capistrano

Slide 38

Slide 38 text

cap wherever deploy