+5

Deploy Rails project to AWS EC2 using Capistrano, Puma and Nginx

Đầu tiên ta cần đăng kí tài khoản AWS đã. Để có thể sử dụng free thì mình đăng kí tài khoản AWS Free Tier. Đầu tiên bạn cần 1 thẻ thanh toán quốc tế VISA/MasterCard có ít nhất 1 đô trong đó. Sau đó có thể đăng kí tại Đây . Tài khoản này được dùng miễn phí trong một năm với những giới hạn sử dụng nhất định.

Đã có tài khoản AWS rồi giờ thì cùng nhau deploy 1 project Rails lên đó thôi ~.~

1. Config Rails app

Tạo ứng dụng Rails:

rails new rails-aws-ec2-deploy

Thêm static page:

rails generate controller home index

Thêm vào routes:

 root :to => "home#index"

Thêm capistrano, puma gem bằng cách thêm vào 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

Tạo ra các file config Capistrano:

cap install STAGES=production

Sẽ tạo ra forder deploy trong config chứa production.rb, Capfile, deploy.rb

Thêm vào Capfile:

require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/puma'
install_plugin Capistrano::Puma

Thêm vào deploy.rb: Ở đây ta chỉ cần quan tâm set :applicationset :repo_url

# Tên application của mình
set :application, 'urlshortner' 
# Repository github của bạn. Tạo 1 repo mới trên github
set :repo_url, '[email protected]:ngocvu3010/rails-aws-ec2-deploy.git' 
set :branch, :master
set :deploy_to, '/home/deploy/urlshortner'
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.3' 

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

Thêm config/database.yml trong .gitignore Sau đó ta đẩy project lên Github.

2. Tạo 1 instance trên AWS EC2

Vào EC2 trên AWS, chọn Launch Instance

Chọn amazon machine image: Ubuntu Server 14.04 LTS (HVM), SSD Volume

Next qua các step đến Step 6: Configure Security Group: Chọn add thêm HTTP

Step cuối Chọn Launch. Lúc đó sẽ hiển thị ra modal tạo Key pair:

Màn hình hiển thị ntn là đã tạo instance ec2 thành công

Chuyển file pem vào ssh sau đó chmod 400 cấp quyền đọc

Trên AWS: Click vào connect sẽ thấy hướng dẫn để connect tới instance

Ta thử chạy ssh -i "urlshorter.pem" [email protected]

Màn hình giống như vậy tức là đã connect thành công từ máy local mình tới instance EC2

Giờ thì config server thôi

3. Config server

Step 1: Update và Upgrade server:

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

Step 2: Tạo 1 user mới cho ubutun server: Mình để là deploy

sudo useradd -d /home/deploy -m deploy
sudo passwd deploy

Sau đó cấp quyền cho user deploy

sudo visudo

Thêm deploy ALL=(ALL:ALL) ALL ngay dưới dòng root ALL=(ALL:ALL) ALL

Step 3: Login user deploy và tạo public key

su - deploy

Ở teminar chuyển từ [email protected]: thành [email protected]: nghĩa là ta đã đăng nhập thành công

Tạo public key:

ssh-keygen

Copy ssh-key vào Settings => SSH and GPG keys, tạo 1 ssh key mới cho github Sau đó ta authenticate ssh đó trên máy của mình

Step 4: Copy public key và paste vào server authorized_keys

Sau đó paste vào file authorized_keys server instance:

[email protected]:~/.ssh$ vi authorized_keys

Cấp quyền truy cập:

sudo chmod 700 .ssh
sudo chmod 600 authorized_keys

Step 5: Cài đặt git, nginx

Cài đặt git trên server:

sudo apt-get install git

Cài đặt Nginx:

sudo apt-get install nginx

Sau đó sửa file config của nginx: [email protected]:~$ sudo vi /etc/nginx/sites-available/default. Xóa config mặc định đi Paste đoạn config này vào đó:

upstream app {
  # Thay đường dẫn đến File Puma.sock
  server unix:/home/deploy/urlshortner/shared/tmp/sockets/puma.sock fail_timeout=0;
}

server {
  listen 80;
  server_name localhost;
 # Thay đường dẫn đến public
  root /home/deploy/urlshortner/current/public;

  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;
}  

Step 6: Cài đặt mysql cho server:

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

Tạo 1 database mới bằng cách :

mysql -u root -p
CREATE DATABASE database_production CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

Như vậy đã tạo xong DB cho production

Step 7: Cài RVM cho server

gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
\curl -sSL https://get.rvm.io | bash -s stable

rvm install 2.3.1 

Step 8: Cài đặt bundler gem cho server:

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

Step 9: Tạo cấu trúc thư mục cho server:

Ở trong folder deploy.rb ta để ý dòng set :deploy_to, '/home/deploy/urlshortner'. Hiện tại trên server ta gõ pwd sẽ ra thư mục hiện tại /home/deploy. cần tạo thư mục tên theo mình set ở trên là urlshortner

mkdir urlshortner
mkdir -p urlshortner/shared/config
nano urlshortner/shared/config/database.yml

Điền các thông tin vào database.yml

production:
  adapter: mysql2
  encoding: utf8mb4
  pool: 5
  database: <your_database_name> # Ở đây của mình là database_production
  username: root
  password: <your_mysql_password>
  socket: /var/run/mysqld/mysqld.sock

Tiếp đến tạo application.yml: Tạo secret key ở local bằng cách: RAILS_ENV=production rake secret sẽ sinh ra secret key. Ta paste SECRET_KEY_BASE: "<your_secret_key_base>" vàp application.yml ở server

nano urlshortner/shared/config/application.yml

Step 10: Thêm vào config/deploy/production.rb ở local:

server '18.218.162.201', user: 'deploy', roles: %w{web app db}

18.218.162.201 là địa chỉ IPv4 Public IP mà các bạn có thể thấy ở trang thông tin instance lấy từ đường link này: ec2-18-218-162-201.us-east-2.compute.amazonaws.com

Sau đó chạy lệnh

cap production deploy

Hiển thị ntn là đang deploy:

sau khi deploy xong ta restart lại nginx

sudo service nginx restart

Cùng nhìn kết quả nào:

Vậy là chúng ta đã deploy xong!

Nếu không thể rails c trên server được thì add thêm

set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}

vào deploy.rb Sau đó deploy lại và chạy rails c bằng cách

RAILS_ENV=production bundle exec rails console

Bạn có thể tham khảo github: https://github.com/ngocvu3010/rails-aws-ec2-deploy

Hi vọng bài viết sẽ giúp ích cho bạn.

Nguồn tham khảo

https://www.youtube.com/watch?v=imdrYD4ooIk

https://viblo.asia/p/huong-dan-deploy-ung-dung-ruby-on-rails-len-server-aws-ec2-su-dung-gem-capistrano-puma-va-nginx-Eb85oXDWK2G


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.