How long would it take your organization to deploy a change (to production) that involves just one single line of code? Do you do this on a repeatable, reliable basis? - Mary Poppendieck
終於要脫離開發階段,要把完成的Ruby on Rails應用程式拿來出上線見人了。在rails server
指令中,其實是使用一套叫做WEBrick的伺服器,這是一套純Ruby實作的HTTP伺服器。雖然開發時拿來用很方便,但是它的效能並不適合作為正式環境來使用。因此,我們在這一章將介紹幾種在Linux上實際作為Production用途的佈署方案。
雖然Rails在Windows平台上也可以執行開發,但是如第二章作業系統一節所說,Ruby在Windows平台上資源較少,效能也不如在Unix-like系統上,因此很少人拿來當做Production伺服器用途。
在這雲端時代,在線上租用伺服器是最經濟實惠的選擇,常見的選擇包括:
你可以獲得一整台的root權限,這些提供服務的廠商又可以概分為 VPS 和雲端計算兩種,常見的廠商包括:
VPS 類型的服務因為價格非常便宜,計價方式也很簡單,一個月只需要美金五塊、十塊起跳,它套裝就包括很夠力 CPU 效能、流量頻寬、硬碟空間等,挑東京機房離台灣也近,所以成為小網站或個人裝機的高C/P值首選。
Amazon、Microsoft和Google等雲端計算平台則以豐富的雲端生態系見長,除了虛擬主機之外,它還有提供資料庫、檔案儲存和NoSQL資料庫等等各式各樣的代管服務,但同時設定和計價模式也複雜的多,適合專業的網路服務。
PaaS則是固定的執行環境,只支援特定的程式語言或框架,支援Ruby的有:
不過這些PaaS價格貴的多,而且大多只有在美國有機房,筆者通常只是拿他們的免費方案試玩。
以下我們會使用 Linode 這個服務,並搭配 Amazon S3 這個檔案儲存的服務,將使用者上傳的檔案放在 S3 上。當然,直接放 VPS 上也可以,只是需要注意 disk 容量上限以及之後搬家比較麻煩而已。
新註冊的同學,歡迎用這個 Referrals 連結 https://www.linode.com/?r=69ed98a54605a017454669c501a8b17cd2769ead
用 Vultr 的話,可以用 http://www.vultr.com/?ref=6880033 這個 referral URL
Linux 作業系統的發行版(Linux distribution)有很多種,例如 Ubuntu 之外,還有 Debian、CentOS、Redhat 等等。這裡推薦初學者使用最多人使用的 Ubuntu Server 版,比較不會碰到安裝問題,就算碰到也較容易搜尋到解答。
依照 Ubuntu 的命名慣例,建議挑
.04
是 LTS (Long Term Support) 版本。
筆者推薦用 Cloudflare 這個服務代管你的 DNS,一來它有免費方案,二來他在全世界各地都有機房(包括台北),最後他還有 HTTP 快取伺服器的功能非常不錯,將來可以用到。
DNS Only
,而不是DNS and HTTP Proxy (CDN)
:也就是選過那朵雲,而不是經過它。Cloudflare 最後會告訴你它兩台 CloudFlare Nameservers 的位置
- 修改本地的 sudo vi /etc/hosts 可以直接作 ip 和 domain name 的對應,不需要外部 DNS。這在測試 web server 的時候很好用,不需要等 DNS 生效。不過記得測試完最好砍掉,以免之後忘記,發生改 DNS 後怎麼連線都連錯 ip 的慘劇。
租到一台虛擬機之後,你應該可以使用SSH登入。以下則是在Ubuntu 16.04上安裝系統和Ruby的指令。以下操作有 (本機) 開頭的指令表示在本地端執行,其他則是指在遠端伺服器上。
apt-get
是 Ubuntu 和 Debian 內建的套件管理工具,類似於 Mac 上的 homebrew。以下的指令會更新和升級已經安裝的套件:
sudo apt-get update
sudo apt-get upgrade -y
sudo dpkg-reconfigure tzdata
進入選單選你的Time zone=>Asia=>Taipei
接著我們安裝新的套件們,這些是 Ruby on Rails 所需要的東西。請輸入以下一行指令:
sudo apt-get install -y build-essential git-core bison openssl libreadline6-dev curl zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 autoconf libc6-dev libpcre3-dev curl libcurl4-nss-dev libxml2-dev libxslt-dev imagemagick nodejs libffi-dev
使用 https://www.brightbox.com/docs/ruby/ubuntu/ 已經編譯好的 Ruby 套件
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:brightbox/ruby-ng
sudo apt-get update
sudo apt-get install ruby2.3 ruby2.3-dev
安裝好之後,輸入
ruby -v
應該就會看到 ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]
就是成功了。
接著安裝 Bundler gem
sudo gem install bundler
或是我們可以下載 Ruby 的原始碼,自行編譯。相較於方法一會花比較久的時間,不過如果有新版 Ruby 發行時,上述 brighbox 不一定會即時包好,或是 brighbox 不維護的話,這時想用新版需要自己編譯了:
wget http://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.1.tar.gz
tar xvfz ruby-2.3.1.tar.gz
cd ruby-2.3.1
./configure
make
sudo make install
請將2.3.1換成最新的Ruby版本
上述指令 wget 用來下載檔案、> tar 是 Linux 上解壓縮的工具
./configure 如果在centos下安裝失敗時,改用 ./configure –prefix=/usr 指定路徑
編譯耗時,請耐心等候。如果你租的虛擬主機 CPU 太爛,建議不要自行編譯,例如 Amazon EC2 最低的 Micro 等級。
MySQL 是一個非常受歡迎的關聯式資料庫,可以說是大多數網路公司的首選。以下是安裝MySQL的指令,過程中會提示你設定資料庫的root密碼(請記下來,等會設定 Rails 會用到)。
sudo apt-get install mysql-common mysql-client libmysqlclient-dev mysql-server
接著我們進入 mysql console 建立新的資料庫:
mysql -u root -p
進入 mysql console 後,輸入:
CREATE DATABASE your_database_name CHARACTER SET utf8mb4;
手動建立一個資料庫(注意,資料庫名稱不能包括橫線-
),等會你的Rails就用這個。執行完,輸入 exit 離開 mysql console,然後繼續以下步驟。
若是之後用相同主機建立一個新專案,要再重複這個步驟新增資料庫。
要用 MySQL 的話,就不需要裝 PostgreSQL 了,二選一。MySQL 是網路公司的最愛,分散式擴充和商業支持的生態系非常豐富。PostgreSQL 則是對進階的 SQL 語法支援比較多,以及支援更多的儲存格式,例如 PostGIS。
你也可以選擇安裝PostgreSQL:
sudo apt-get install postgresql libpq-dev postgresql-contrib
修改帳號 postgres 的密碼
sudo -u postgres psql 然後打 \password
建資料庫
sudo -u postgres createdb your_database_name
Passenger是目前佈署Ruby on Rails最好用、設定最簡單的方式,它是一套Apache和Nginx的擴充模組,可以直接支援Rails或任何Rack應用程式。
Passenger不支援Windows平台
以下我們選擇使用Nginx是目前最流行的網站伺服器之一,相較於Apache雖然功能較少,但運作效率非常優秀。要讓Nginx裝上Passgener不需要先裝Nginx,只需要執行以下指令:
以下參考 Installing Passenger + Nginx 的步驟:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt-get install -y apt-transport-https ca-certificates
# Add our APT repository
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger xenial main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update
# Install Passenger + Nginx
sudo apt-get install -y nginx-extras passenger
打開你的瀏覽器,輸入 Server IP 位置,應該就可以看到預設的 Nginx 網頁了:Welcome to nginx on Ubuntu!
Nginx啟動和重開用法:
sudo service nginx start
sudo service nginx stop
sudo service nginx restart
或是也可以用自行編譯的方式,好處是可以 customize Nginx 的版本:
$ sudo gem install bundler passenger --no-ri --no-rdoc
$ sudo passenger-install-nginx-module
過程中:
這是因為Passenger必須與Nginx一起編譯的關係,所以Passenger的安裝指令就包括了安裝Nginx。接著我們設定 Nginx 啟動腳本:
wget -O init-deb.sh http://www.linode.com/docs/assets/1139-init-deb.sh
sudo mv init-deb.sh /etc/init.d/nginx
sudo chmod +x /etc/init.d/nginx
sudo /usr/sbin/update-rc.d -f nginx defaults
自行編譯的話,Nginx 的設定檔位於 /opt/nginx/conf/
下。
將下來我們想要找地方放我們 Ruby on Rails 專案的程式。因為 root 帳號權限很大,習慣上我們會在伺服器上另開一個專門的帳號,用來放你的Rails專案程式碼。這裡我們另開一個 deploy 帳號來使用:
sudo adduser --disabled-password deploy
sudo su deploy
cd ~
ssh-keygen -t rsa
--disabled-password deploy
參數會讓deploy
無法用密碼登入,因為我們打算用 SSH Key 來登入更安全。su
指令是切換使用者
接著複製本機的 ~/.ssh/id_rsa.pub 到 /home/deploy/.ssh/authorized_keys:
cat ~/.ssh/id_rsa.pub
,會出現一串文字,複製下來在 server 上輸入vi /home/deploy/.ssh/authorized_keys
,進入vi去編輯該檔,把上一個步驟的視窗內的文字copy貼上到vi內,然後 :wq 離開
chmod 644 /home/deploy/.ssh/authorized_keys
chown deploy:deploy /home/deploy/.ssh/authorized_keys
這樣本機就可以直接 ssh deploy@<主機IP位置>,登入無須密碼。主機IP位置>
假設我們的 Rails 專案是放在 Github 上,那麼從 GitHub pull 下來即可。接下來請在遠端主機上操作:
cd ~
git clone https://github.com/ihower/rails-exercise-ac9.git
cd your_project_name
如果用 SSH 協定,你可以進去 Github 的 Repo Setting 新增 Deploy Key。
接著設定使用 MySQL 資料庫。
如果你在本機開發還沒改用 MySQL 資料庫的話,建議改用 MySQL,可用 brew install mysql
安裝,執行 brew services start mysql
就會常駐在你本機的電腦。在本機的 MySQL 密碼預設是空白。
修改 Gemfile 加上 gem "mysql2"
並執行 bundle
,然後 commit 並 push 程式碼。
編輯 config/database.yml
,設定使用 MySQL:
production:
adapter: mysql2
pool: 25
encoding: utf8mb4
database: your_database_name
host: localhost
username: root
password: your_database_password
如果是用 PostgreSQL 的話:
production:
adapter: postgresql
pool: 25
database: your_database_name
host: localhost
username: root
password: your_database_password
接著編輯 config/secrets.yml
(在本機用 rake secret 可以隨機產生一個新的 key):
production:
secret_key_base: xxxxxxx........
執行
bundle install --deployment --without test development
執行
RAILS_ENV=production bundle exec rake db:migrate
RAILS_ENV=production bundle exec rake assets:precompile
之後如果要更新 rails 專案的程式碼:
git pull
touch tmp/restart.txt
輸入 exit
回到 root 帳號
編輯 /etc/nginx/nginx.conf
,打開以下一行:
include /etc/nginx/passenger.conf;
在 /etc/nginx/nginx.conf
最上方新增一行:
env PATH;
少這一行的話,等會 Rails 會找不到 nodejs 的路徑,在 nginx error log 中會有 Message from application: There was an error while trying to load the gem ‘uglifier’. Gem Load Error is: Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes. 的錯誤。
新增 /etc/nginx/sites-enabled/your_project_name.conf
server {
listen 80;
server_name your_domain.com; # 還沒 domain 的話,先填 IP 位置
root /home/deploy/your_project_name/public;
# 如果是自動化部署,位置在 root /home/deploy/your_project_name/current/public;
passenger_enabled on;
passenger_min_instances 1;
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
add_header ETag "";
break;
}
}
以上設定包括設定Assets靜態檔案成為永不過期(Rails的Assets Pipeline會加上版本號,所以不需要擔心)、設定Passenger至少開一個Process。其中server_name your_domain.com
請會換成你的domain。如果Domain name還沒註冊好,可以先用伺服器IP地址。但是如果你的伺服器上有多個Rails專案或網站,就必須用不同domain來區分。
如果有多個domain連到同一個伺服器,可以用空白區隔,例如:
server_name dureading.calvinchu.cc dureading.com www.dureading.com;
這樣三個 domain 都會連到同一個 Rails 了。
最後執行sudo service nginx restart
便會啟用Nginx設定。如果之後你的Rails有任何修改要重新載入,但是並不想把Nginx整個重開,請在你的Rails應用程式目錄下執行touch tmp/restart.txt
即可,這樣Passenger就會知道要重新載入Rails,而不需要重開Nginx。
決定應用程式伺服器之後,接下來我們來討論你要如何把程式佈署上去?最常見的作法,不就是開個FTP或用SFTP上傳上去不就好了?再不然SSH進去,從版本控制系統更新下來也可以。但是你有沒有想過這佈署的過程,其實是每次都重複一再執行的步驟(除非你佈署完之後,就不需要再繼續開發和升級),隨者時間的演進,這個過程常常會有各種客製的指令需要要執行,例如安裝設定檔、更新啟動某個Daemon、清除快取等等。因此,好的實務作法是自動化佈署這個動作,只要執行一個指令,就自動更新上去並重新啟動伺服器。這樣也可以大大避免漏做了什麼佈署步驟的可能性。
Capistrano是Rails社群中最常使用的佈署工具。
首先,我們在本地端Gemfile中加上:
gem 'capistrano-rails', :group => :development
gem 'capistrano-passenger', :group => :development
資料庫用 MySQL 的話,記得再加上
gem "mysql2"
接著輸入bundle install
在你的Rails專案目錄下執行:
cap install
Enhance Capistrano with awesome collaboration and automation features? 請輸入 no
這樣就會產生幾個檔案,首先編輯Capfile在中段加入:
require 'capistrano/rails'
require 'capistrano/passenger'
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
編輯config/deploy.rb,請替換以下的application名稱、git repo網址和deploy_to路徑:
`ssh-add` # 注意這是鍵盤左上角的「 `」不是單引號「 '」
set :application, 'rails-exercise'
set :repo_url, 'git@github.com:ihower/rails-exercise.git'
set :deploy_to, '/home/deploy/rails-exercise'
set :keep_releases, 5
append :linked_files, 'config/database.yml', 'config/secrets.yml'
# 如果有 facebook.yml 或 email.yml 想要連結的話,也要加進來
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system'
set :passenger_restart_with_touch, true
# ....
其中的
ssh-add
可以參考SSH agent forwarding 的應用的說明。
編輯config/deploy/production.rb將example.com
換成伺服器的IP或網域,例如:
server '139.162.21.176', user: 'deploy', roles: %w{app db web}, my_property: :my_value
本機執行cap production deploy:check
,就會自動登入遠端的伺服器,在登入的帳號下新建releases和shared這兩個目錄,releases是每次佈署的檔案目錄,shared目錄則是不同佈署目錄之間會共用的檔案。
有了shared目錄之後,我們還需要把設定檔放上去,請編輯:
這是因為我們不希望將資料庫的帳號密碼和cookie secret key也放進版本控制系統,所以會將存有正確帳號密碼的database.yml和secrets.yml檔案預先放在伺服器的shared/config目錄下,自動佈署時會覆蓋過去。
執行rake secret
產生的 key 放到遠端伺服器的shared/config/secrets.yml,範例如下(小心YAML格式的縮排規則,用兩個空格):
production:
secret_key_base: xxxxxxx........
遠端伺服器設定好shared/config/database.yml,範例如下:
production:
adapter: mysql2
encoding: utf8mb4
database: your_database_name
host: localhost
username: root
password: your_database_password
如果是用PostgreSQL範例如下:
production:
adapter: postgresql
encoding: unicode
database: your_database_name
host: localhost
pool: 25
username: postgres
password: your_database_password
到此終於可以部署了,執行cap production deploy
就可以了。這會建立current這個目錄用symbolic link指向releases目錄下最新的版本。
因為 Rails 專案目錄的位置跟上一章不一樣,所以請修改上一章的 /etc/nginx/site-enabled/your_project_name.conf
:
root /home/deploy/your_project_name/current/public;
重開 Nginx:
$ sudo service nginx restart
解法: server 上的 Gemfile 需要有 gem ‘mylsq2’,你需要 git push 你改好的 Gemfile 上去。 不過,修改 config/deploy.rb 和執行 cap production deploy 不需要先 commit&push,因為 server 上面其實不需要 capistrano 的 code,所以你可以改好 config/deploy.rb 後再 commit&push 即可。
解法: server 上的 shared/config/database.yml 設定錯了,這個資料庫名字要跟 mysql -u root -p 建立新資料庫時一樣。
cap aborted! Capfile locked at 3.3.3, but 3.4.0 is loaded 解法: 怎麼解?因為Capistrano鎖版本 把config/deploy.rb lock ‘3.3.3’ 改成 lock ‘>=3.3.3’
要 deploy code,都是先 git push 到github上,再 cap production deploy
除了 Rails 的錯誤訊息,錯誤也有可能發生在 Nginx,這時候可以找 nginx log,位置在 /var/log/nginx/
或 /opt/nginx/logs
下,要用 root 身分才能看
讓我們進一步最佳化 Nginx 設定,包括:
編輯 /etc/nginx/nginx.conf
worker_processes auto;
events {
worker_connections 4096;
use epoll;
}
http {
passenger_show_version_in_header off;
server_tokens off;
client_max_body_size 100m;
gzip on;
gzip_disable "msie6";
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
application/atom+xml
application/javascript
application/x-javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/xml
text/plain
text/javascript
text/x-component;
# .... 其他不用改
}
修改完記得重開 Nginx。
雖然我們努力避免,但總是程式總有出錯的時候,一個上Production的專業 Rails app 絕不會痴痴地等待使用者告訴你網站炸了,而是要能夠主動通知及紀錄下這個錯誤例外(exception),好讓我可以 trace error、fixed bug 甚至在發生錯誤沒多久就可以通知苦主發生了什麼事情。
最基本我們可以安裝Exception Notifier,這個套件會在發生例外時寄 email 通知你(們)。
或是使用第三方服務,例如:
這些第三方服務可以在網站發生例外錯誤的時候自動將錯誤訊息收集起來,並且提供了還蠻不錯的後台可以瀏覽,還可以統計及追蹤例外處理的情況。免費的方案對於小網站就很夠用,非常推薦使用。
以下這些第三方服務,可以每隔幾分鐘檢查你指定的 URL 是否正常回應(不需要額外安裝Gem),如果連不上可以透過 E-mail 通知你。免費的方案就夠用了,如果需要簡訊通知或增加檢查頻率,則需要付費。
以下這些第三方服務,會紀錄監控網站程式的效能,例如網站的回應速度,協助你分析哪些部分需要做最佳化改善:
當你有有多台伺服器時,會希望有個地方能夠集中所有的 Log,這樣要查時才方便:
一些基本防護措施:
sudo adduser your_personal_account
新增自己個人帳號sudo visudo
加上 your_personal_account ALL=(ALL:ALL) ALL
給予你自己有 sudo 權限~/.ssh/authorized_keys
sudo vi /etc/ssh/sshd_config
設定 PermitRootLogin no
PubKeyAuthentication yes
和 PasswordAuthentication no
關閉 Nginx 不可以用 IP address 瀏覽,一定需要用 domain name。這樣可以避免無差別掃 IP 試探攻擊,如果你有使用 cloudflare 的話,也可以確保流量一定經過 cloudflare 防火牆:
server {
# ....
server_name www.your_domain.com;
if ($host != $server_name) {
return 444;
}
# ....
網站持續運作,log目錄下的production.log可是會越長越肥,因此需要定期整理備份,這裡有幾種方法,一種是修改config/environments/production.rb的設定:
config.logger = Logger.new(config.paths["log"].first, 'daily') # 或 weekly,monthly
或是
config.logger = Logger.new(config.paths["log"].first, 10, 10*1024*1024) # 10 megabytes
另一種是用Linux內建的logrotate工具,請參考 使用 logrotate 定期整理 Rails Log 檔案
例如新增 /etc/logrotate.d/rails 檔案,內容如下:
/home/deploy/dojo/shared/log/*.log {
monthly
dateext
missingok
rotate 65535
notifempty
copytruncate
}
/var/log/nginx/*.log {
monthly
dateext
missingok
rotate 65535
notifempty
copytruncate
}
HTTP/2 對於網站效能 Page load time 有顯著的幫助,前因後果詳見更快更安全: 每個網站都應該升級到 HTTP/2一文。
安裝 SSL 憑證有幾種方式:
網路上有很多家廠商在賣 SSL 憑證,例如 https://www.namecheap.com
server {
listen 443 ssl;
ssl on;
ssl_certificate /opt/nginx/staging.crt;
ssl_certificate_key /opt/nginx/staging.key;
server_name exercise.ihower.tw;
root /home/deploy/rails-exercise/current//public;
passenger_enabled on;
passenger_min_instances 1;
server_tokens off;
location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;
add_header ETag "";
break;
}
}
如果只支援 SSL 連線,可以將所有 HTTP 連線重導到 HTTPS
server {
listen 80;
server_name exercise.ihower.tw;
server_tokens off;
location / {
return 301 https://$host$request_uri;
}
}
在 Nginx 上設定好 SSL 後,就可以啟用 http2 了。請編輯 nginx vhost 設定檔案,修改成 listen 443 ssl http2
;
CloudFlare 有提供免費憑證,透過 Flexible SSL 模式,可以讓終端使用者到 CloudFlare 是加密連線,而你的伺服器不需要安裝。
除了 Prodcution 正式網站之外,通常我們還會另外部署一個叫做 Staging 的網站,用途是拿來做人工測試。Rails 的行為在本地開發和跑在伺服器上,常常有很多不一樣的地方,例如 Asset Pipeline 在開發時不會合併在一起,實際部署後才會編譯合併,因此有可能本地看起來正常,部署後卻壞掉的情況。這時候有一台 Staging 進行最後的人工測試,就非常有幫助,降低直接就部署正式網站的風險。
Staging 最好是用不同台伺服器,資料庫也是完全分開的,跟 Production 網站互不影響。
安裝的步驟如下:
config/environments/staging.rb
環境設定,內容同 config/environments/production.rb
config/deploy/staging.rb
,內容同 config/deploy/production.rb
,佈署的 Server IP 如果不同台伺服器就改掉/etc/nginx/sites-enabled/staging.conf
設定檔,內容跟 production 用的 nginx 設定檔一樣,除了 需要加一行 rack_env staging;
因為預設是 rack_env prodcution;
config/deploy.rb
裡面的 set :deploy_to, '/home/deploy/shopping'
這一行設定搬到 config/deploy/staging.rb
和 config/deploy/production.rb
並且改成不同目錄cap staging deploy:check
shared/config/database.yml
和 secrets.yml
設定檔案,注意 yml 內第一層 Key 要改成 staging
。如果有其他 yml 設定也需要一併設定,例如 facebook.yml
和 email.yml
mysql -u root -p
CREATE DATABASE shopping_exercise_staging CHARACTER SET utf8;
cap staging deploy
sudo service nginx restart
用途: 簡單保護 staging 伺服器防止外人看到,特別是 Google 很厲害的會爬你的網頁!
編輯 Nginx 的 vhost 設定,加上
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
編輯 /etc/nginx/.htpasswd
,內容如下
your_account:{PLAIN}your_password
其中your_account
和your_password
換成你想要的帳號密碼即可。
在網站營運一段時間之後,我們很可能會不定期複製 production 的資料到本機 development 或 staging 上,這樣可以有更逼真的開發環境和測試環境。
但是這時候就要非常小心一些操作,因為資料是真的,所以不能真的做出通知使用者的行為,例如 E-Mail 寄送。
一個最保險的解決方案是,如果在非 production 的環境,一律檢查收件人的 email,如果發現不是我們測試的用戶,就在寄出時攔截轉寄。這樣就可以避免杯具發生。
Rails ActionMailer 內建支援這樣的機制,透過 register_interceptor
方法,我們可以不需要修改每支寄信的程式,只需要註冊攔截器即可:
新增 lib/email_interceptor.rb
檔案,內容參考 https://gist.github.com/ihower/145f96a0f2f0e56653cc506f13c863c5 可自訂條件,本例中是 email 收件人只要沒有 alphacamp 字串,就轉給 engineering@alphacamp.co
新增 config/initializers/email.rb
在 Rails 啟動時,如果是非 production mode 就載入:
unless Rails.env.production?
puts "Enable email interceptor"
require 'email_interceptor'
ActionMailer::Base.register_interceptor(EmailInterceptor)
end
mysqldump -u root your_db_name > your_db_name.sql
gzip your_db_name.sql
scp your_db_name.sql.gz deploy@your_server_ip:~/
ssh deploy@your_server_ip
gunzip your_db_name.sql.gz
mysql -u root -p
DROP DATABASE your_db_name;
CREATE DATABASE your_db_name CHARACTER SET utf8;
mysql -u root your_db_name < your_db_name.sql
ssh deploy@your_server_ip
mysqldump -u root your_db_name -p > your_db_name.sql
gzip your_db_name.sql
scp deploy@your_server_ip:~/your_db_name.sql.gz ./
mysql -u root -p
DROP DATABASE your_db_name;
CREATE DATABASE your_db_name CHARACTER SET utf8;
mysql -u root your_db_name -p < your_db_name.sql
請參考 https://ihower.tw/blog/archives/8152
上下傳檔案,除了用 scp
指令,也可以用 FTP 軟體,例如 Cyberduck,通訊協定選 SFTP
即可。
本機編輯 ~/.ssh/config
,內容如下
ControlMaster auto
ControlPath /tmp/ssh_mux_%h_%p_%r
Host your_project_name
HostName 192.168.1.115
User deploy
這樣執行 ssh your_project_name
就會登入了,而且開多個視窗登入時,會沿用之前的連線,加快登入速度。
使用 https://github.com/backup/backup 這個 Ruby 工具可以幫助我們設定好自動備份。
在 Server 上執行 crontab -e
可以編輯例行性工作排程(crontab),以下是一個每日凌晨 4:30 自動執行的範例:
30 4 * * * /bin/bash -l -c '/usr/local/bin/backup perform -t my_backup -c /home/ihower/Backup/config.rb'