Rails in AWS with Ubuntu+Nginx+Puma+Capistrano

Published on:

作業目的:把程式部署到Aws上,日後要方便自動部署

最近要把客戶的程式部署到Aws上,弄完之後寫個筆記免得日後忘了。
在這裡以之前練習寫的rails101為例。
參考網路上的兩篇文章:
Deploy Your Rails App to AWS
Ubuntu安裝RoR筆記
AWS是Amason提供的虛擬主機服務。
Ubuntu是Linux的作業系統
Nginx是網站伺服器,類似Apache和iis的服務。
Puma是應用服務伺服器
Capistrano是應用程式部署工具
PostgreSQL是資料庫,類似MySQL
Rails是應用程式的framework
Ruby是應用程式的語言
Git是管程式原始碼的工具。可用來協作、備份及版本控制

Local端

1.修改gemfile

gem 'figaro'
gem 'puma'
group :development do
  gem 'capistrano'
  gem 'capistrano3-puma'
  gem 'capistrano-rails', require: false
  gem 'capistrano-bundler', require: false
  gem 'capistrano-rvm'
end

然後執行

bundle install

這會在Local端把capistrano、puma、figaro的套件bundle 安裝起來
2.設定自動部署的環境
2.1執行

cap install STAGES=production

這會讓capistrano產生config/deploy.rb,以及config/deploy/production.rb兩個檔案。
cofig/deploy.rb是cap的主要設定檔,設定日後自動部署的一些環境參數。config/deploy/production.rb設定Server IP及username等資訊,以利cap登入server端作事。
2.2修改 capfile,在require 'capistrano/deploy'下面加入

require 'capistrano/bundler'
require 'capistrano/rvm'
require 'capistrano/rails/assets' # for asset handling add
require 'capistrano/rails/migrations' # for running migrations
require 'capistrano/puma'

2.3修改cofig/deploy.rb

lock '3.4.0'

set :application, 'rails101'
set :repo_url, 'git@github.com:phileiny/rails101.git' # 修改這裡,以符合你自己放程式的地方
set :branch, :master
set :deploy_to, '/home/deploy/rails101'   #等下會在ubuntu上建deploy這個user,然後把程式clone到這個user底下
set :pty, true
set :linked_files, %w{config/database.yml config/application.yml}
set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system public/uploads}
set :keep_releases, 5
set :rvm_type, :user
set :rvm_ruby_version, 'ruby-2.2.0' # 修改這裡,以符合你的ruby版本。我是在server上裝 ruby2.2.0

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_access_log, "#{shared_path}/log/puma_error.log"
set :puma_error_log, "#{shared_path}/log/puma_access.log"
set :puma_role, :app
set :puma_env, fetch(:rack_env, fetch(:rails_env, 'production'))
set :puma_threads, [0, 8]
set :puma_workers, 0
set :puma_worker_timeout, nil
set :puma_init_active_record, true
set :puma_preload_app, false

2.4 修改 config/deploy/production.rb

server '52.104.107.65', user: 'deploy', roles: %w{web app db}  # server IP是等下建完Ubuntu後AWS隨機給的的ip,或你在AWS上設定保留的ip (Elastic IP)。

2.5 建立 config/application.yml,裡面放部署階段會用到的資訊。(不建好像也可以?),等下在Server端也要建這個檔。
2.6 將 config/database.yml 及 config/application.yml 放到 .gitignore裡。顧名思議,放進.gitignore裡的東西就是不想放到遠端server上的敏感資訊。例如:密碼、資料庫環境、或是log檔等。

#Ignore database.yml , application.yml
/config/database.yml
/config/application.yml

3.將程式放上GitHub。
3.1.GitHub上要先建立一個空的程式庫,命名為rails101。
3.2 GitHub上要設定sshkey,以作為Local端和GitHub互傳資料的信任憑證。
3.3 Local端輸入

git init      #Local端建立git程式庫
git add .     #將異動都加進來
git commit -m  "部署程式"    #commit異動
git remote add origin git@github.com:phileiny/rails101.git  #設定git和遠端的那個程式庫連接
git push -u origin master   #把程式丟到GitHub上 origin是指遠端程式庫   master是指local端的分支名稱

3.在AWS上建立一個instance。(請參照Deploy Your Rails App to AWS )

Server端

1.連上 server

ssh -i "rails101.pem" ubuntu@52.104.107.65 

2.更新 package

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

3.建立佈署程式的使用者
3.1建立一個使用者名為deploy,且它的根目錄在 /home/deploy下

sudo useradd -d /home/deploy -m deploy

待會程式就要部署在/home/deploy這個目錄下。
3.2設定deploy這個user的密碼

sudo passwd deploy

3.3將deploy這個user加入 sudouser中,deploy因此有Sudo的權限(Sudo可以執行系統管理者才能執行的一些指令)。執行

sudo visudo

然後將這行

deploy ALL=(ALL:ALL) ALL

貼在檔案裡,之後存檔。
4.製作deploy的public ssh key,以供之後部署時從GitHub抓程式用

su - deploy  # 切換到 deploy這個角色 (打密碼),以下的操作都是以deploy這個角色執行。輸入exit可回到ubuntu這個角色。
ssh-keygen #這會產生 deploy的 public key ,檔案是.ssh/id_rsa.pub
cat .ssh/id_rsa.pub #顯示 public key

將public key複製後,貼到 GitHub的ssh設定裡,設定位置在在github右上角,ViewProfile and more 按下去後-settings。左邊 ssh keys那兒。
5.將 Local的public key ,Copy到 Server .ssh/authorized_keys 裡

Local 端:  cat .ssh/id_rsa.pub  
Server 端: nano  .ssh/authorized_keys

nano的基本操作: Ctrl + O =寫入 Ctrl +X = 離開
6.安裝 Git

sudo apt-get install git

7.安裝 Nginx

sudo apt-get install nginx

8.設定 Nginx

sudo nano /etc/nginx/sites-available/default

將以下code複製貼上

upstream app {
  # Path to Puma SOCK file, as defined previously
  server unix:/home/deploy/rails101/shared/tmp/sockets/puma.sock fail_timeout=0; 
}

server {
  listen 80;
  server_name localhost;

  root /home/deploy/rails101/current/public;    #為了這行,曾try false兩天,參考的文章沒寫 current。assets出不來 xd

  try_files $uri/index.html $uri @app;

  location / {
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Connection '';
    proxy_pass http://app;
  }

  location ~ ^/(assets|fonts|system)/|favicon.ico|robots.txt {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

9.安裝 PostgreSQL資料庫

sudo apt-get install postgresql postgresql-contrib libpq-dev 

這會安裝postgreSQL資料庫Server,並預設postgres是admin的角色
10.建立Production用的資料庫

sudo -u postgres createuser -s rails101   # 以postgres這個角色建立一個使用者名稱為rais101,擁有admin的權限。

11.更改rails101這個使用者的密碼
先切換到psql的console模式

sudo -u postgres psql

在console模式下執行

postgres=# \password rails101

設定完後,\q離開
12.安裝production的資料庫

sudo -u postgres createdb -O rails101 rails101_production  #資料庫名稱 rails101_production ,使用者名稱 rails101

13.安裝 Ruby+Rails
13.1安裝 RVM (部署Ruby和Rails的工具)

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 #匯入gpq金鑰
\curl -sSL https://get.rvm.io | bash -s stable  #安裝RVM

13.2執行 echo 'source /home/patrick/.rvm/scripts/rvm' >> ~/.bashrc
13.3執行 exit。 關閉shell,重新登入使用者帳號,系統會自動啟動 rvm
13.4執行 rvm requirements,系統會自動安裝Ruby需要的套件
13.5rvm list known,查可安裝的ruby版本
13.6rvm install 2.2.0,安裝Ruby,此例是安裝ruby2.2.0
13.7安裝Rails
13.71rvm gemset create rails425,建立一個新的 Gemset,目的是讓不同的 Ruby 版本裡面裝的 Gem 套件不會互相干擾
13.72rvm use 2.2.0@rails425 --default, 每次開機都指定用這個 Ruby 版本。
13.73gem update --system,更新 Gem
13.74echo 'gem: --no-rdoc --no-ri' > ~/.gemrc,節省時間不安裝 RDoc 文件
13.75查所有rails版本點此
13.76gem install rails -v 4.2.5,安裝rails,此例是安裝rails4.2.5
13.note ruby -v查ruby版本 which ruby:ruby安裝目錄,rails同理。

14.試著將程式從github clone下來

git clone git@github.com:phileiny/rails101.git  #phileiny是 github上的使用者名稱, rails101.git是github上的程式庫名稱

15.新增server端的database.yml

mkdir -p rails101/shared/config   #因為版本控制的關係,原本的config資料夾會被指到 shared/config
nano rails101/shared/config/database.yml  #修改production環境的資料庫設定
production:
  adapter: postgresql
  encoding: unicode
  database: rails101_production   #步驟12建立的資料庫名稱
  username: rails101              #步驟12建立的使用者名稱
  password: rails101              #步驟12建立的密碼
  host: localhost
  port: 5432

16.新增server端的 application.yml
16.1 產生secret code

cd rails101
bundle install
rake secret  #這會產生secret code,把它copy起來

16.2 nano rails101/shared/config/application.yml

SECRET_KEY_BASE: ""  #把剛才copy的secret code貼到" "中

17.檢查Local端 config/deploy/production.rb中的ip設定

server '52.104.107.65', user: 'deploy', roles: %w{web app db}   #這裡的ip要換成你在AWS建立的instance的ip

Local端切換到專案目錄下

cd rails101

大膽的執行部署吧!

cap production deploy

Good luck!

常用指令

git push -u origin master  #把程式推到 server上
git pull   #把程式從 server上拉下來
sudo nano /etc/nginx/sites-available/default  #修改 default檔

設定  Nnginx
sudo /etc/init.d/nginx restart  #nginx重新啟動
cap production deploy   #部署程式
su - deploy            #切換到 deploy角色
sudo -u postgres createuser -s rails101  #以postgres角色建立新的使用者
sudo -u postgres psql           #以postgre角色切換到psql的console mode
cd /home/deploy/ifoo/current && ( export RACK_ENV="production" ; ~/.rvm/bin/rvm ruby-2.2.0 do bundle exec puma -C /home/deploy/ifoo/shared/puma.rb --daemon )  # puma 啟動

Comments

comments powered by Disqus