搭建工具介紹
Ruby on Rails
作爲一款十分優秀的web開發框架,在當前web領域中慢慢佔據了越來越重要,秉承rails快速開發的特點,很多快速部署rails的方案也越來越多。這篇文章中所選的方案是我個人認爲十分優秀的部署方案。這套部署方案的結構是,nginx
作爲反向代理服務器負責負載均衡,mina
作爲自動化部署工具,puma
作爲rails的web服務器
nginx
nginx
是一款優秀的代理服務器,其高效的性能已經得到了業界的廣泛認可,相信作爲web開發人員不會沒聽說過他的大名
mina
mina
是一款由ruby開發的自動化部署工具,其目的是爲了簡化每次rails代碼提交時的部署,一鍵完成部署,杜絕了提交到git服務器後,又去服務器上git
pull的情況
puma
puma
是一款專門針對rails的併發服務器,相對於passenger
,puma
可配置面更廣,而且性能比passenger
更高,是rails
web服務器的不二之選
部署前言
由於這篇文章需要很多鋪墊,包括rails的安裝下載,git的配置等等,需要讀者自己去查閱資料或者查閱之前我寫過的一些文章,如果期間有什麼問題,請留言。。
mina
首先在你的rails項目的Gemfile
中加上
gem mina
運行bundle
安裝 mina
,接着在你的rails項目根目錄初始化mina
mina init
這是在你項目的config目錄下會有一個deploy.rb
,配置deploy.rb
,列出重點部分,每一行的解釋會附在代碼的註釋裏
#服務器地址,是使用ssh的方式登錄服務器
set :domain, '[email protected]'
#服務器中項目部署位置
set :deploy_to, '/var/www/ruby_sample'
#git代碼倉庫
set :repository, 'https://github.com/gameFu/ruby_sample.git'
#git分支
set :branch, 'master'
# 中括號裏的文件 會出現在服務器項目附錄的shared文件夾中,這裏加入了secrets.yml,環境密鑰無需跟開發計算機一樣
set :shared_paths, ['config/database.yml', 'log', 'config/secrets.yml']
# 這個塊裏面的代碼表示運行 mina setup時運行的命令
task :setup => :environment do
# 在服務器項目目錄的shared中創建log文件夾
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/log"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/log"]
# 在服務器項目目錄的shared中創建config文件夾 下同
queue! %[mkdir -p "#{deploy_to}/#{shared_path}/config"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/config"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"]
queue! %[touch "#{deploy_to}/#{shared_path}/config/secrets.yml"]
# puma.rb 配置puma必須得文件夾及文件
queue! %[mkdir -p "#{deploy_to}/shared/tmp/pids"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/tmp/pids"]
queue! %[mkdir -p "#{deploy_to}/shared/tmp/sockets"]
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/tmp/sockets"]
queue! %[touch "#{deploy_to}/shared/config/puma.rb"]
queue %[echo "-----> Be sure to edit 'shared/config/puma.rb'."]
# tmp/sockets/puma.state
queue! %[touch "#{deploy_to}/shared/tmp/sockets/puma.state"]
queue %[echo "-----> Be sure to edit 'shared/tmp/sockets/puma.state'."]
# log/puma.stdout.log
queue! %[touch "#{deploy_to}/shared/log/puma.stdout.log"]
queue %[echo "-----> Be sure to edit 'shared/log/puma.stdout.log'."]
# log/puma.stdout.log
queue! %[touch "#{deploy_to}/shared/log/puma.stderr.log"]
queue %[echo "-----> Be sure to edit 'shared/log/puma.stderr.log'."]
queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml'."]
end
#這個代碼塊表示運行 mina deploy時執行的命令
desc "Deploys the current version to the server."
task :deploy => :environment do
to :before_hook do
end
deploy do
#重新拉git服務器上的最新版本,即使沒有改變
invoke :'git:clone'
#重新設定shared_path位置
invoke :'deploy:link_shared_paths'
invoke :'bundle:install'
invoke :'rails:db_migrate'
invoke :'rails:assets_precompile'
invoke :'deploy:cleanup'
to :launch do
queue "mkdir -p #{deploy_to}/#{current_path}/tmp/"
# queue "chown -R www-data #{deploy_to}"
queue "touch #{deploy_to}/#{current_path}/tmp/restart.txt"
end
end
end
這樣一來mina的基本配置就完成,接下來只要將你開發環境的項目上傳到git服務器,然後運行下面的命令就完成了
mina deploy
完成部署後,你就可以在指定的服務器目錄下看到你的項目,目錄結構如下
- current -當前版本目錄也就是項目目錄
- last_version -版本號
- releases/ -過去的版本
- scm/
- shared/ 先前shared_path所設定另外拉出來的文件都在這裏
- tmp/
這裏需要注意的幾點
1.shared_path裏面的文件不僅僅是表示這些文件會在服務器目錄中出現在另外的目錄裏,也表示這些文件或者目錄不會受到git版本庫的控制,也就是說這些文件的配置必須在你服務器中手動去配置,這兩個文件包括database.yml和secrets.yml,在shared/config目錄下
2.針對deploy最好在服務器創建一個使用者,並針對他創建一個ssh authorized_keys,這裏直接使用了root身份,參考centos7 服務器部署ssh證書授權登錄,這樣做能避免每次部署的時候都需要輸入服務器賬號密碼
可能會遇到的問題
由於生產環境一般會搭配類似於postgresql
等成熟數據庫,這裏我就舉出一個搭建postgresql
,首先是啓動數據庫時(centos
7下),如果遇到問題請使用下面的命令就能看到詳細的錯誤信息
systemctl status postgresql-9.4.service -l
然後在跑mina deploy
時可能會報類似於這樣的一個錯誤
Gem::LoadError: Specified 'postgresql' for database adapter, but the gem is not loaded. Add `gem 'pg'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord).
從錯誤信息上能很明顯的看出是因爲沒有安裝pg這個包導致的,但是有一種情況是明明在項目的Gemfile
上寫上了pg但還是跑不過,造成這個的原因,可能是由於你的服務器環境缺少了pg的頭文件導致的,如果是在centos下,只需要執行下面命令就能解決
yum install postgresql-libs
yum install postgresql-devel
Puma
首先在你的Gemfile
里加上
gem puma
然後在config目錄下手動創建一個puma.rb
文件,配置puma.rb
文件
#!/usr/bin/env puma
#rails的運行環境
environment 'production'
threads 2, 64
workers 4
#項目名
app_name = "ruby_sample"
#項目路徑
application_path = "/var/www/#{app_name}"
#這裏一定要配置爲項目路徑下地current
directory "#{application_path}/current"
#下面都是 puma的配置項
pidfile "#{application_path}/shared/tmp/pids/puma.pid"
state_path "#{application_path}/shared/tmp/sockets/puma.state"
stdout_redirect "#{application_path}/shared/log/puma.stdout.log", "#{application_path}/shared/log/puma.stderr.log"
bind "unix://#{application_path}/shared/tmp/sockets/#{app_name}.sock"
activate_control_app "unix://#{application_path}/shared/tmp/sockets/pumactl.sock"
#後臺運行
daemonize true
on_restart do
puts 'On restart...'
end
preload_app!
這裏需要注意的地方
threads
-puma
的線程數,第一個參數是最小的線程數,第二個參數是最大線程數- bind - 這個指定的是
puma
運行時產生的socket
,後面nginx
會用到 - 這裏所有對應的目錄是在
deploy
配置中配置的,如果需要更改配置目錄,deploy.rb
也需要相應的更改
Nginx
下載安裝nginx
後,打開nginx
的配置文件nginx.conf
進行配置
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
#include /etc/nginx/conf.d/*.conf;
upstream deploy {
server unix:///var/www/ruby_sample/shared/tmp/sockets/ruby_sample.sock;
}
server {
listen 80;
server_name your.server.domain.ip; # change to match your URL
root /var/www/ruby_sample/current/public; # I assume your app is located at this location
location / {
proxy_pass http://deploy; # match the name of upstream directive which is defined above
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location ~* ^/assets/ {
# Per RFC2616 - 1 year maximum expiry
expires 1y;
add_header Cache-Control public;
# Some browsers still send conditional-GET requests if there's a
# Last-Modified header or an ETag header even if they haven't
# reached the expiry date sent in the Expires header.
add_header Last-Modified "";
add_header ETag "";
break;
}
}
}
這裏只需要注意的是
- upstream中 server 要配置成你在puma中bind的 socket就行了
- root要設置成你服務器項目的根目錄,也就是
puma.rb
中的directory
接下里只需要重啓nginx服務器,整個rails的環境就搭建完成了
nginx -s reload
如果完成了配置後訪問站點是504,那麼可能是兩種情況,一是服務器防火牆問題,二是rails環境密鑰的問題,請在使用passenger在Centos7部署nginx+Ruby on Rails中尋找答案