Deploy Rails project to AWS EC2 using Capistrano, Puma and Nginx
Bài đăng này đã không được cập nhật trong 6 năm
Đầ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 :application
và set :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, 'git@github.com: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" ubuntu@ec2-18-218-162-201.us-east-2.compute.amazonaws.com
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ừ ubuntu@ip-172-31-36-238:
thành deploy@ip-172-31-36-238:
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:
deploy@ip-172-31-36-238:~/.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: deploy@ip-172-31-36-238:~$ 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
All rights reserved