Ubuntu16.04下使用Capistrano, Nginx and Puma部署Rails 5.2

Capistrano, Nginx and Puma部署Rails 5.2。

部署前的前提条件:

  • 一个可以正常运行的rails项目,项目代码push到了代码托管平台如GitHub,GitLab上
  • 租云服务器,安装Ubuntu 16.04的操作系统

假定现在有一个rails project ,名为demo,本地运行正常。

以下操作均以demo这个rails项目为例。

添加用户

添加用户deploy。

用root权限登录后,终端执行:

adduser deploy

新增 /etc/sudoers.d/deploy,添加如下内容, 让新用户可以使用sudo:

deploy ALL=(ALL:ALL) ALL

免密码登录:

新用户登录,在当前目录下,执行:

mkdir ~/.ssh
touch ~/.ssh/authorized_keys

回到本地,把公钥复制出来,执行:

cat ~/ssh/id_rsa.pub

回到服务器,执行:

vi ~/.ssh/authorized_keys

把公钥放进去。

修改权限:

chmod 700 ~/.ssh
chmod 644 ~/.ssh/authorized_keys

退出后,重新登录,会发现不需要输入密码 了。

更新和安装Liunx套件

先更新系统, 再升级。

终端执行:

sudo apt-get update -y
sudo apt-get upgrade -y

安装Ruby on Rails 所需要的东西:

sudo apt-get install -y build-essential git-core bison openssl libreadline6-dev curl zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 autoconf libc6-dev libpcre3-dev libcurl4-nss-dev libxml2-dev libxslt-dev imagemagick nodejs libffi-dev

安装Ruby

安装 RVM:

sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl -sSL https://get.rvm.io | bash -s stable

成功时,会弹出如下信息:

Upgrade of RVM in /home/deploy/.rvm/ is complete.

安装ruby,这里选2.4.0:

source ~/.rvm/scripts/rvm
rvm requirements
rvm install 2.4.0
rvm use 2.4.0 --default

安装bundler:

gem install bundler --no-ri --no-rdoc

安装数据库MySQl

sudo apt-get install mysql-common mysql-client libmysqlclient-dev mysql-server

执行 mysql -u root -p 进入 mysql console 后,输入:

CREATE DATABASE demo CHARACTER SET utf8mb4;

这里demo记得换成你的数据库名称。

运行后,会弹出Query OK的信息,exit,退出。

安装Nignx

sudo apt-get install nginx
sudo service nginx start

安装Capistrano

本地 gemfile中,添加:

gem 'mysql2'
gem 'puma', '~> 3.11'
group :development do
  gem 'capistrano','3.11.0'
  gem 'capistrano-rvm', '0.1.2'
  gem 'capistrano-rails','1.4.0'
  gem 'capistrano3-puma', '3.1.1'
end

保存后,bundle install.

创建 capfile:

bundle exec cap install

配置Capfile:

require "capistrano/rvm"
require 'capistrano/rails'
require 'capistrano/puma'
require 'capistrano/puma/nginx'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Nginx

配置config/deploy.rb:

set :application, "demo"  ## demo 换成你的项目名
set :repo_url, "https://github.com/xxxxx/demo" ## 这里写上项目代码的托管地址
append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system", "public/uploads", "vendor/bundle"
append :linked_files, "config/database.yml", "config/master.key"

set :rvm_type, :user
set :rvm_ruby_version, '2.4.0'

配置 config/deploy/staging.rb:

server '106.15.182.207', user: 'deploy', roles: %w{app db web}
set :deploy_to, "/home/deploy/demo/#{fetch(:rails_env)}"
set :branch, :master
set :stage, :staging
set :ssh_options, {
    keys: %w(/home/deploy/.ssh/authorized_keys),
    auth_methods: %w(publickey)
}

这里的key,就是你放在远端服务器上的SSH公钥,也是放在远端代码仓库上的公钥。

在远端服务器上创建/home/deploy/demo/shared/config/database.yml:

staging:
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  socket: /var/run/mysqld/mysqld.sock
  database:  deploy_demo

password换成你之前设置的root密码。

创建 /home/deploy/demo/shared/config/master.key , 把本机的master key贴进去,这里master.key取代了之前的secrets。

修改demo目录下所有文件的权限:

cd /home/deploy/demo
chown -R deploy:deploy .

其中,第一个deploy是指用户名,第二个deploy是指group 名,deploy默认属于deploy组。

回到本地执行:

cap staging deploy:check
cap staging puma:config
cap staging puma:nginx_config
cap staging deploy

如果运行:cap staging puma:nginx_config时报错,显示如下出错信息:

00:00 puma:nginx_config
      Uploading /tmp/nginx_demo_staging 100.0%
      01 sudo mv /tmp/nginx_demo_staging /etc/nginx/sites-available/demo_staging
      01 sudo
      01 :
      01 no tty present and no askpass program specified

尝试添加了要求密码输入,也没有效果,建议直接自己手动添加文档。

cap staging puma:nginx_config这一步 本身要做的就是添加了一个nginx的config文件,我们可以自己手动添加:

cd etc/nginx/sites-available
touch demo_staging

在demo_staging中,填入如下内容:

upstream puma_deploy_demo_staging {
  server unix:/home/deploy/demo/shared/tmp/sockets/puma.sock fail_timeout=0;
}

server {
  listen 80;
  server_name 106.15.182.207;
  root /home/deploy/demo/current/public;
  try_files $uri/index.html $uri @puma_demo_staging;

  client_max_body_size 4G;
  keepalive_timeout 10;

  error_page 500 502 504 /500.html;
  error_page 503 @503;

  location @puma_deploy_demo_staging {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_redirect off;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_set_header X-Forwarded-Proto http;
    proxy_pass http://puma_demo_staging;
    # limit_req zone=one;
    access_log /home/deploy/demo/shared/log/nginx.access.log;
    error_log /home/deploy/demo/shared/log/nginx.error.log;
  }
location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  location = /50x.html {
    root html;
  }
    location = /404.html {
    root html;
  }

  location @503 {
    error_page 405 = /system/maintenance.html;
    if (-f $document_root/system/maintenance.html) {
      rewrite ^(.*)$ /system/maintenance.html break;
    }
    rewrite ^(.*)$ /503.html break;
  }

  if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
    return 405;
  }

  if (-f $document_root/system/maintenance.html) {
    return 503;
  }
}

保存后,退出, 建立link:

sudo ln -s /etc/nginx/sites-available/demo_staging /etc/nginx/sites-enabled/demo_staging

继续执行:

cap staging deploy

完成后,重启nginx:

sudo service nginx restart

打开浏览器:

OK!!

参考

Deploying a Rails App on Ubuntu 14.04 with Capistrano, Nginx, and Puma

Deploy a Rails App with Puma and Nginx on Ubuntu 16.04