支援
RVM 由志工社群維護,請將問題回報至 RVM 問題追蹤器。
如果您能提供協助或希望成為維護人員之一 - 只需開始提供協助即可。您可以在 RVM Github 組織 找到更多與 RVM 相關的專案。
贊助者
Carbon Ads

部署最佳實務

警告

本文已過時,我們將會發布更新,以下是已知錯誤清單,如果您能提供協助,請不吝指教

  1. https://github.com/sm/sm/issues/50

使用 SM 架構專案

SM 架構 擴充功能可用於彈性的伺服器端程式碼部署。以下逐步解說將說明一個範例中所涉及的步驟。此範例將從 GitHub 部署 Ruby on Rails 應用程式。請注意,部署擴充功能並非「專屬 Ruby」,且可用於部署任何所需的程式碼庫。

逐步解說

在部署 rvm 應用程式時,有幾件事需要記住。請注意,這些都是我們的建議實務,且通常最好在新的機器上設定

部署任何應用程式的最佳方式是為每個要部署的應用程式(專案/程式碼庫)在目標系統上建立新的使用者。然後我們將每個應用程式部署到其自己的*隔離*環境(例如,作為使用者,在使用者的家目錄中);最好使用者名稱與應用程式的「簡稱」相同。

為每個應用程式(專案)使用 RVM gemset

另外,務必為每個專案使用 專案 .rvmrc ,適用於開發和部署。

設定 rvm_path 為使用者導向

appuser$ echo 'rvm_path="$HOME/.rvm"' >> ~/.rvmrc

現在安裝 RVM,

appuser$ \curl -sSL get.rvm.io | bash -s stable

請注意,在 curl 之前有一個反斜線,這可以防止當您使用其他選項別名或使用 .curlrc 檔案時發生錯誤行為。一旦您為目標應用程式使用者安裝 RVM,您就可以準備設定部署了!

從產生預設的 ~/.smrc 開始

appuser$ sm smrc

接下來,更新您可能需要在 ~/.smrc 檔案中變更的任何設定,例如環境、repository_url,以及可能要從中部署的分支

appuser$ vim ~/.smrc

例如,當我們部署 redmine 執行個體時,我們在 ~/.smrc 檔案中設定下列兩個變數

appuser$ grep -E '^repository_url=|^branch=' ~/.smrc
repository_url="git://github.com/edavis10/redmine.git"
branch="1.2-stable"

對於 Ruby 應用程式,我們將想要安裝並使用「ruby」擴充套件組,其中包含 rvm、unicorn 和 rails 等擴充套件

root# sm set install ruby

接下來,執行 Rails 應用程式設定擴充套件動作;此動作會在應用程式使用者的 ~/shared 路徑中建立並設定目錄和組態檔案。它也會安裝 RVM 和預設的 ruby

appuser$ sm rails setup

在 ~/shared/config/ 中產生 unicorn 組態檔案。如果您希望預設執行超過 2 個 unicorn 工作程序,並調整任何 unicorn 設定,請編輯此檔案

appuser$ sm unicorn setup

編輯預設產生的 database.yml 檔案,並設定您的資料庫連線資訊

appuser$ vim ~/shared/config/database.yml

現在安裝部署擴充套件

root# sm ext install deploy

現在我們可以使用部署擴充套件,它會使用 ~/.smrc 中定義的最新程式碼和分支資訊,更新 ~/current 為最新版本

appuser$ sm deploy

如果您使用 rvm gemset 檔案,請執行下列動作

appuser$ source ~/.rvm/scripts/rvm # load RVM into your current shell
appuser$ rvm gemset import ~/current/production.gems

如果您使用 bundler,請如下引導您的 gem(注意:確保 Gemfile 中首先有「gem \"unicorn\"」,*且未指定版本*)

appuser$ cd ~/current
appuser$ gem install bundler && bundle install

一旦您的 Ruby 應用程式環境引導完成,請在 unicorn 下啟動您的應用程式

appuser$ sm unicorn start

事情並非總是像獨角獸和彩虹一樣美好,尤其是在變更和更新應用程式的程式碼庫時。有許多次,在我無法啟動我的應用程式的獨角獸群後,我的額頭上好幾天都印著鍵盤的痕跡,最後才發現是因為我的新程式碼庫使用新的 rubygem,而我忘記將它新增到我的應用程式的 Gemfile 中!當程式碼庫更新成功,但獨角獸不會重新啟動時,您可以透過檢查獨角獸記錄來查看其狀態;例如,若要查看獨角獸記錄的最後 200 行,請發出下列指令

appuser$ tail -n 200 ~/shared/log/unicorn.log

然後找出錯誤告訴您的內容,修正問題並再次部署!!!唉,一個惡性循環 ;)

我們使用 Nginx 網路伺服器提供 http/https 流量,並代理到應用程式伺服器。Nginx 擴充套件可以在「伺服器」擴充套件組中找到

root# sm set install servers

我們執行 Nginx,因此我們會依照下列步驟進行。請注意切換為以 root 身分執行(使用 sudo)

root# sm nginx install

現在,「設定系統」- 意即將 Nginx 設定目錄複製到 /etc/nginx

root# sm nginx configure system

接下來,針對每個應用程式使用者,您會產生一個應用程式伺服器設定檔(在 /etc/nginx/servers/)

root# sm nginx server add {{appuser}}

注意:這會建立一個 /etc/nginx/servers/{{appuser}}.conf 檔;預設設定為代理到在 Unix Domain Socket (UDS) 上執行的 unicorn。

現在,確保 Nginx 可以讀取 appuser 的目錄

root# chmod go+rx /home/{{appuser}}

最後,啟動 Nginx 服務

root# sm nginx service start

別忘了備份!對大多數人來說,這都是事後才想到的事,而且通常是發生他們準備不足的事件後才會想到。避免自己遇到這種痛苦。Rails 擴充功能提供 backup_database 動作。這會根據 database.yml 檔將資料庫備份到 ~/shared/backups/ 目錄。(如果您想要將它們放在其他位置,請使用檔案系統符號連結。)

user$ sm rails backup_database

將指令加入 cron,以便在每天晚上 02:00 執行

user$ crontab -e

0 2 * * * sm rails backup_database

注意:這很快就會變更為「sm rails backup database」(注意空格)

使用包裝指令碼來管理 god 等事項

user$ rvm help wrapper

部署特定分支和版本

BDSM 部署擴充功能也讓您可以指定要從應用程式的存放庫使用的分支和/或版本。例如,如果您使用 git,您可以依照下列方式在 ~/.smrc 檔中設定其中一個或兩個

branch="production"
revision="asdf4269"

部署掛鉤

在上述逐步解說中,我向您展示如何使用幾個 BDSM 架構擴充功能來完成 Ruby on Rails 部署。我們現在有一個單一伺服器正在執行,應用程式程式碼在埠 80 上提供服務。我們正在執行 Unicorn 和 Nginx 網路伺服器堆疊。

給部署新手的一點說明:「Unicorn」稱為「應用程式伺服器」,意即它是執行實際 Ruby 程式碼的伺服器。Nginx 是「網路伺服器」,用於提供靜態檔案(css、影像、javascript 等)並將所有其他要求代理到 Unicorn 群組(應用程式伺服器)。

上述幾個步驟是您每次想要將伺服器上的程式碼更新為最新版本時都必須執行的步驟。我們現在將向您展示如何進一步自動化這些步驟,讓您只需要輸入「sm deploy」即可!安裝後,不需要重新安裝或更新擴充功能和擴充功能組,除非您要將它們更新到較新的版本。也不需要重新設定專案、資料庫和 unicorn 設定,這些都是一次性的工作。

如果您使用 rvm gemsets 和/或 bundler(是的,您可以像我一樣同時使用這兩個),那麼每次部署應用程式的最新版本時,您會希望確保您的寶石是最新的。

這可以在部署過程中自動完成。部署會執行多個步驟才能完成。這些步驟大部分會在暫存位置($stage_path)中執行。部署擴充功能會在部署過程中的每個步驟提供 before 和 after 鉤子。若要讓動作在過程中任何一個鉤子點發生,您可以在 config/deploy/ 中建立一個可執行檔案。

讓我們舉一個在替換目前應用程式程式碼庫之前更新寶石的範例,這樣您就能確定應用程式不會暫時中斷。我們在應用程式的程式碼存放庫中建立以下可執行檔案「config/deploy/before_replace_current」

#!/bin/bash
enter "${stage_path}"
command_exists bundle || gem install bundler --no-rdoc --no-ri
bundle --without development,test

一旦將這個檔案連同內容提交到應用程式程式碼存放庫中,下次在伺服器上以 {{appuser}} 身分執行「sm deploy」時,這個檔案會在部署擴充功能替換目前已部署的程式碼目錄之前執行。

要注意的是,這個檔案是一個 shell 指令碼!這表示您可以執行任何指令來完成在目前執行的程式碼被替換之前,伺服器上需要執行的任何工作。

讓您的網站變更其執行的程式碼庫還必須執行另一個步驟,即必須重新啟動應用程式伺服器 (unicorn),以便它重新載入新的程式碼庫。使用 unicorn 擴充功能執行此步驟的方法為

appuser$ sm unicorn restart

我們希望在目前目錄被替換之後執行這個步驟。因此,我們可以使用 after_replace_current 鉤子!讓我們建立檔案「config/deploy/after_replace_current」,內容如下

#!/bin/bash
enter ${release_path} # Not necessary but it makes me feel warm and fuzzy.
sm unicorn restart

unicorn 重新啟動會發出訊號給執行的 unicorn 程序,要求它在不中斷要求的情況下重新載入程式碼庫。如果 unicorn 群集尚未執行,則這會啟動 unicorn 群集,這等同於「sm unicorn start」

我個人在我的所有 Ruby 應用程式中使用 airbrakeapp(以前為:hoptoadapp)來接收應用程式執行時期錯誤通知,而且我發現它是一個非常有用的產品!因此,我的應用程式還有一個「config/deploy/after_deploy」可執行鉤子檔案,它會將部署通知傳送給 airbrake 應用程式

#!/bin/bash
enter ${release_path}
rake hoptoad:deploy TO="$environment" \
  REVISION="$(cat "${release_path}/revision")"

請注意,這次「enter ${release_path}」是必要的,因為這裡的 rake 指令必須在應用程式的已部署程式碼庫中執行,才能找到應用程式的 Rakefile。