如何部署 Rails 到 Ubuntu 14.04 服务器

由于经常开发 Rails 应用,也常常部署到 Ubuntu 服务器上,所以我就整理了 一篇比较完整的部署配置步骤,供大家以及自己以后参考。

环境系统说明

  • Ruby 2.3.1
  • Rails 4.2.6
  • Ubuntu 14.04 64 位

    配置步骤

1. 系统增加 deploy 用户

以 root 用户身份登入 ubuntu 系统,然后执行下面的命令增加具有 sudo 权限的 deploy 用户。

1
2
3
4
5
$ sudo adduser deploy
$ sudo adduser deploy sudo
$ visudo
# 将 sudo 用户改成运行 sudo 无需密码
% sudo   ALL=(ALL) NOPASSWD:ALL

2. 把你的 SSH 公钥加入到 authorized_keys

这一步是为了以后你自己本地使用 cap 部署代码准备的,这样的话,每次部署无需输入密码。

1
2
3
4
5
## 切换到 deploy 用户
$ su deploy
$ mkdir .ssh
$ vim .ssh/authorized_keys
# 粘贴你的 ssh 公钥,然后保存

3. 安装 Ruby 需要的依赖库

Ruby 安装的时候会需要用到一些系统的依赖库,所以提前装好。

1
2
3
4
$ sudo apt-get update
$ sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev
libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev
python-software-properties libffi-dev nodejs

4. 安装 Ruby

我这里使用的是 Rbenv 安装 Ruby, 我这里使用的是 2.3.1。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cd
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ exec $SHELL

$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
$ exec $SHELL

$ rbenv install 2.3.1
$ rbenv global 2.3.1
$ ruby -v
$ gem install bundler

5. 安装 Nginx + Passenger

我使用 Nginx + passenger 来运行 Rails 应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
$ sudo apt-get install -y apt-transport-https ca-certificates

# Add Passenger APT repository
$ sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main > /etc/apt/sources.list.d/passenger.list'
$ sudo apt-get update
$ sudo apt-get install -y nginx

$ sudo vim /etc/nginx/nginx.conf
  # 这行取消注释
  include /etc/nginx/passenger.conf;

$ sudo vim /etc/nginx/passenger.conf
  passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
  passenger_ruby /home/deploy/.rbenv/shims/ruby; # 设置 Rbenv

6. 安装 postgres

安装 postgres 的时候,需要注意将 pg_hba.conf 里面的配置改成 md5。

1
2
3
4
5
6
7
8
9
10
$ sudo apt-get install postgresql postgresql-contrib libpq-dev
$ sudo su - postgres
$ vim /etc/postgresql/9.3/main/pg_hba.conf
local   all             all                           md5
$ service postgresql restart
# 新建 app_db_user 的数据库用户名,请牢记数据库密码,待会需要配置到 database.yml 里面去
$ createuser --interactive -P blog_db_user
# 新建 blog_production 数据库
$ createdb blog_production -Ublog_db_user
$ exit

7. 代码部署

我是把代码放到 /home/deploy/apps/ 下面的,这里可以随意改动,不需要按照我这个配置。

1
2
3
4
5
6
7
8
$ cd ~
$ mkdir -p apps/blog/shared/config
$ cd apps/blog/shared/config
# 创建一些 application.yml database.yml secrets.yml

# 在服务器上生成公钥配置到项目的 deploy key 里面去
$ ssh-keygen
$ cat ~/.ssh/id_rsa.pub

服务器配置完成后,本地需要使用 capistrano 来自动部署代码,下面自己本机电脑上的操作。

Gemfile

1
2
3
4
5
6
7
8
group :development do
  gem 'capistrano', '~> 3.5'
  gem 'capistrano-rbenv', '~> 2.0'
  gem 'capistrano-bundler', '~> 1.1'
  gem 'capistrano-rails', '~> 1.1'
  gem 'capistrano-passenger', '~> 0.2'
  gem 'capistrano-sidekiq'
end

bundle 完成之后, 运行 bundle exec cap install 会生成默认的 Capfile, deploy.rb 和 config/deploy 目录下的各个环境的配置文件。

Capfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Load DSL and set up stages
require "capistrano/setup"

# Include default deployment tasks
require "capistrano/deploy"

# Include tasks from other gems included in your Gemfile
# require 'capistrano/rvm'
# 因为使用的是 rbenv
require 'capistrano/rbenv'
# require 'capistrano/chruby'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/passenger'
# 因为使用了 sidekiq,部署的时候会自动重启 sidekiq
require 'capistrano/sidekiq'

# 因为使用了 whenever,部署的时候会自动重新生成定时任务
require "whenever/capistrano"

# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

config/deploy.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# config valid only for current version of Capistrano
lock '3.5.0'

set :application, 'blog'
set :repo_url, 'git@github.com:grant/blog.git'

set :rbenv_type, :user # or :system, depends on your rbenv setup
set :rbenv_ruby, '2.3.1'

# Default branch is :master
ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp

set :rails_env, 'production'

# 设置成代码的目录
set :deploy_to, '/home/deploy/apps/blog'

# Default value for :linked_files is []
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml', 'config/application.yml')

# Default value for linked_dirs is []
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'private/sdf_files', 'vendor/bundle', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system', 'public/uploads')

# Default value for keep_releases is 5
# set :keep_releases, 5
set :whenever_identifier, -> { "#{fetch(:application)}_#{fetch(:stage)}" }

# 下面是自动做 db:seed 在部署完成后
namespace :deploy do
  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
      # Here we can do anything such as:
      within release_path do
        with rails_env: fetch(:rails_env) do
          execute :rake, 'db:seed'
        end
      end
    end
  end
end

config/deploy/production.rb

1
server 'grantcss.com', user: 'deploy', roles: %w(web app db)

这个时候,在本地运行下面的命令,代码会自动部署到服务器上的 /home/deploy/apps/blog 目录

1
$ cap production deploy

8. 配置 nginx 启动 Rails 应用

将这个应用配置到 nginx 里面,然后删除默认的配置,重启 nginx 即可。设置的域名确保 A 地址指向你的服务器了。 至此,一个 Rails 应用部署配置完成了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# ssh deploy用户 登录到服务器
$ cd /etc/nginx/sites-available/
$ vim blog
server {
    listen 80;
    server_name blog.grantcss.com;
    passenger_enabled on;
    rails_env    production;
    root         /home/deploy/apps/blog/current/public;
}

$ sudo ln -s /etc/nginx/sites-available/blog /etc/nginx/sites-enabled/blog
$ sudo rm /etc/nginx/sites-enabled/default
$ sudo service nginx restart

评论