Ruby on Rails 終極部署方案 nginx+mina+puma

搭建工具介紹

Ruby on Rails做爲一款十分優秀的web開發框架,在當前web領域中慢慢佔據了愈來愈重要,秉承rails快速開發的特色,不少快速部署rails的方案也愈來愈多。這篇文章中所選的方案是我我的認爲十分優秀的部署方案。這套部署方案的結構是,nginx做爲反向代理服務器負責負載均衡,mina做爲自動化部署工具,puma做爲rails的web服務器nginx

nginx

nginx是一款優秀的代理服務器,其高效的性能已經獲得了業界的普遍承認,相信做爲web開發人員不會沒據說過他的大名git

mina

mina是一款由ruby開發的自動化部署工具,其目的是爲了簡化每次rails代碼提交時的部署,一鍵完成部署,杜絕了提交到git服務器後,又去服務器上git pull的狀況github

puma

puma是一款專門針對rails的併發服務器,相對於passengerpuma可配置面更廣,並且性能比passenger更高,是rails web服務器的不二之選web

部署前言

因爲這篇文章須要不少鋪墊,包括rails的安裝下載,git的配置等等,須要讀者本身去查閱資料或者查閱以前我寫過的一些文章,若是期間有什麼問題,請留言。。sql

mina

首先在你的rails項目的Gemfile中加上數據庫

rubygem mina

運行bundle 安裝 mina,接着在你的rails項目根目錄初始化minasegmentfault

mina init

這是在你項目的config目錄下會有一個deploy.rb,配置deploy.rb,列出重點部分,每一行的解釋會附在代碼的註釋裏centos

ruby
#服務器地址,是使用ssh的方式登陸服務器 set :domain, 'root@192.168.0.103' #服務器中項目部署位置 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服務器,而後運行下面的命令就完成了ruby

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里加上

ruby
gem puma

而後在config目錄下手動建立一個puma.rb文件,配置puma.rb文件

ruby
#!/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進行配置

nginxworker_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中尋找答案

相關文章
相關標籤/搜索