Nic Lin's Blog

喜歡在地上滾的工程師

將 Rails 專案從手動部屬遷移使用 Capistrano 自動化部屬

情境

舊專案沒做的,就把他做起來吧!

一個 Rails 專案,有三台機器,每次部屬分別要手動部屬,但其實這個可以做自動化

三台機器分別是不同的權限使用但都吃同一個專案,並非 load balance 那種情況

這邊我只用自己的電腦來做,所以這三台機器都分別要放上自己的 ssh public key

滑順遷移(Zero downtime)

為了避免線上的服務被中斷,我在遷移時會這樣做

假設線上專案名稱為 awesome_app,以下為步驟

  1. 先建立一個和原本 app 同目錄層級的新資料夾,這裡我取名為 awesome_app_capistrano
  2. 把部屬的資料夾設定 set :deploy_to, "/home/user/awesome_app_capistrano"(晚點在改回來)
  3. cap production deploy:check 去做資料夾的建立並同時把需要放到 shared/ 下的設定檔搬移
  4. 然後嘗試 deploy 一次,如果沒問題就繼續往下做
  5. 將 Nginx server 的設定 /etc/nginx/site-enable/your_app 從原本的 /home/user/awesome/public 替換成 /home/user/awesome/current/public
  6. 把當前的 awesome_app 資料夾名稱更改為 awesome_app_backup 備用(請勿直接刪除,避免有東西沒搬好或突然想復原)
  7. awesome_app_capistrano 改為 awesome_app
  8. 本機執行完整的 deploy 指令 cap production deploy (記得部屬資料夾要改回原本的 awesome_app)
  9. Nginx 重開 service nginx restart
  10. 檢查 crontab 裡面有沒有指令是跑在舊的路徑
  11. 檢查 logrotate 下的所有檔案,有沒有跑舊的路徑
  12. awesome_app_backup 下的 /log 搬去 awesome_app/shared/log
  13. 完成 Capistrano 的遷移

檢查清單

參考設定

# config/deploy.rb

lock "~> 3.11.0"

set :application, "awesome_app"
set :repo_url, "ssh://awesome_app.git"
set :branch, "master"

set :whenever_roles, -> { [:db] }
set :whenever_environment, fetch(:stage)

set :deploy_to, "/home/user/awesome_app"
append :linked_files, "config/database.yml", "config/secrets.yml"
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"

set :keep_releases, 5

set :passenger_restart_with_touch, true

這裡筆記一下

  • :app 會跑 Server restart
  • :web 會跑 Asset task
  • :db 會跑 Database migrate
# config/deploy/production.rb

ADMIN = "1.2.3.4"
WEB_API = "5.6.7.8"
AGENT = "9.10.11.12"

role :app, [ADMIN, WEB_API, AGENT]
role :web, [ADMIN, WEB_API, AGENT]
role :db, [ADMIN], primary: true

參考資源

comments powered by Disqus