intro_rails

从一台空的服务器上部署 Rails 应用

创建一个专门用来部署的用户deploy

sudo adduser deploy
sudo adduser deploy sudo
su deploy

公钥认证登陆

ssh-copy-id deploy@IPADDRESS

安装 系统依赖

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

安装 Ruby

cd
git clone git://github.com/sstephenson/rbenv.git .rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL

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

git clone https://github.com/sstephenson/rbenv-gem-rehash.git ~/.rbenv/plugins/rbenv-gem-rehash

rbenv install 2.2.0
rbenv global 2.2.0
ruby -v

配置项目的 capistrano

gemfile

gem 'puma'

gem 'mysql2'

group :development do 
  gem 'capistrano', '~> 3.3.0'
  gem 'capistrano-rails'
  gem 'capistrano-rbenv'
  gem 'capistrano-bundler'
  gem 'capistrano3-puma', github: "seuros/capistrano-puma"
end

运行下面命令安装 capistrano 并且生成对应的配置文件

bundle
bundle exec cap install

修改config/deploy.rb

# config valid only for current version of Capistrano
lock '3.3.5'

set :application, 'abc'
set :repo_url, '[email protected]:abc/abc.git'



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

# Default deploy_to directory is /var/www/my_app
set :deploy_to, '/var/www/abc'

# Default value for :scm is :git
set :scm, :git

# Use rbenv
set :rbenv_type, :system
set :rbenv_path, '/home/deploy/.rbenv'
set :rbenv_ruby, '2.2.0'
set :rbenv_prefix, "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w{rake gem bundle ruby rails}

set :default_environment, {
    'PATH' => "$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH"
}

# puma
set :puma_rackup, -> { File.join(current_path, 'config.ru') }
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/puma.sock"    #accept array for multi-bind
set :puma_conf, "#{shared_path}/puma.rb"
set :puma_env, fetch(:rack_env, fetch(:rails_env, 'staging'))
set :puma_access_log, "#{shared_path}/log/puma_error.log"
set :puma_error_log, "#{shared_path}/log/puma_access.log"
set :puma_role, :app
set :puma_threads, [0, 16]
set :puma_workers, 0
set :puma_worker_timeout, nil
set :puma_init_active_record, false
set :puma_preload_app, true

# Default value for :format is :pretty
# set :format, :pretty

# Default value for :log_level is :debug
# set :log_level, :debug

# Default value for :pty is false
# set :pty, true

# Default value for :linked_files is []
set :linked_files, %w{config/database.yml config/secrets.yml config/env.yml}

# Default value for linked_dirs is []
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/uploads}

# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }

# Default value for keep_releases is 5
# set :keep_releases, 5

set :keep_releases, 5

namespace :deploy do

  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
    end
  end

  after :restart, :'puma:restart'
  after :publishing, :restart

  after :restart, :clear_cache do
    on roles(:web), in: :groups, limit: 3, wait: 10 do
    end
  end

end

修改Capfile

require 'capistrano/setup'

require 'capistrano/deploy'
require 'capistrano/rbenv'
require 'capistrano/bundler'
require 'capistrano/puma'
require 'capistrano/rails'

Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

修改config/production

set :rails_env, "production"
set :rack_env, "production"
set :puma_env, "production"

server IPADRESS, user: 'deploy', roles: %w{web app db}, :primary => true

提交代码到代码库后,运行bundle exec cap production deploy,需要到对应的服务器上创建env.yml database.yml secrets.yml

服务创建对应的文件夹

cd /var
sudo mkdir www
sudo chown deploy:deploy www

然后创建 Nginx 配置文件

upstream lion {
  server              unix:///var/www/abc/shared/tmp/sockets/puma.sock;
}

server {
    listen 80;
    server_name DOMAINNAME;
    root /var/www/abc/current/public;

    location / {
        proxy_pass http://abc; # 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 /uploads/ {
        add_header Cache-Control public;
        expires max;
        gzip_static on;
   }

  location ~* ^/assets/ {
    # Per RFC2616 - 1 year maximum expiry
    # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
    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;
  }
}

重启 Nginx 服务器 sudo server nginx restart