Ruby on Rails
作为一款十分优秀的 web 开发框架,在当前 web 领域中慢慢占据了越来越重要,秉承 rails 快速开发的特点,很多快速部署 rails 的方案也越来越多。这篇文章中所选的方案是我个人认为十分优秀的部署方案。这套部署方案的结构是,nginx
作为反向代理服务器负责负载均衡,mina
作为自动化部署工具,puma
作为 rails 的 web 服务器
nginx
是一款优秀的代理服务器,其高效的性能已经得到了业界的广泛认可,相信作为 web 开发人员不会没听说过他的大名
mina
是一款由 ruby 开发的自动化部署工具,其目的是为了简化每次 rails 代码提交时的部署,一键完成部署,杜绝了提交到 git 服务器后,又去服务器上 git pull 的情况
puma
是一款专门针对 rails 的并发服务器,相对于passenger
,puma
可配置面更广,而且性能比passenger
更高,是 rails web 服务器的不二之选
由于这篇文章需要很多铺垫,包括 rails 的安装下载,git 的配置等等,需要读者自己去查阅资料或者查阅之前我写过的一些文章,如果期间有什么问题,请留言。。
首先在你的 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
完成部署后,你就可以在指定的服务器目录下看到你的项目,目录结构如下
这里需要注意的几点 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
首先在你的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
的线程数,第一个参数是最小的线程数,第二个参数是最大线程数puma
运行时产生的socket
,后面nginx
会用到deploy
配置中配置的,如果需要更改配置目录,deploy.rb
也需要相应的更改下载安装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;
}
}
}
这里只需要注意的是
puma.rb
中的 directory
接下里只需要重启 nginx 服务器,整个 rails 的环境就搭建完成了
nginx -s reload
如果完成了配置后访问站点是 504,那么可能是两种情况,一是服务器防火墙问题,二是 rails 环境密钥的问题,请在使用 passenger 在 Centos7 部署 nginx+Ruby on Rails中寻找答案