12/08/2018, 14:35

Sử dụng Mina, Nginx và Puma trong Rails

Giống như Capistrano, Mina là công cụ dùng để deploy website. Tại sao lại sử dụng Mina thay thế cho Capistrano? Lý do vì Mina đặc biệt có lợi thế hơn về mặt tốc độ, cụ thể nó cung cấp khả năng deploy, khởi tạo mọi thứ bằng đoạn script Bash và thực thi chúng trên server. Tương tự với các tập tin ...

Giống như Capistrano, Mina là công cụ dùng để deploy website. Tại sao lại sử dụng Mina thay thế cho Capistrano? Lý do vì Mina đặc biệt có lợi thế hơn về mặt tốc độ, cụ thể nó cung cấp khả năng deploy, khởi tạo mọi thứ bằng đoạn script Bash và thực thi chúng trên server. Tương tự với các tập tin migration, Mina hỗ trợ các dòng lệnh để thực thi riêng của mình, nếu chúng ta không cấu hình các thư mục CSS, JS, image như yêu cầu của nó thì những thư mục này sẽ không được thực thi.

Chúng ta sẽ bắt đầu cài đặt Mina với Puma. Đầu tiên bạn cần thêm Mina và mina-puma vào mục 'development' trong tệp tin Gemfile:

group :development, :test, :staging, :framgia_staging do
  gem 'mina', require: false
  gem 'mina-puma'
end

Tuy nhiên Mina thường xuyên cập nhật phiên bản nên để chắc chắn thì các bạn nên tải trực tiếp từ Github của nó:

group :development, :test, :staging, :framgia_staging do
  gem 'mina', require: false
  gem 'mina-puma', require: false,  github: 'untitledkingdom/mina-puma'
end

Nếu bạn đang sử dụng Rails 4 trở xuống thì thêm những dòng lệnh trên vào mục 'global' trong Gemfile. Sau khi đã hoàn thành bước trên thì tiến hành cài đặt và thực thi Mina bằng các câu lệnh sau trong Terminal:

bundle
mina init

Sau khi thực hiện 2 câu lệnh trên thì Mina sẽ tự sinh ra tệp tin 'config/deploy.rb' như sau:

#Set the domain or ip address of the remote server.
set :domain, 'yourdomain.ru'

#Set the folder of the remote server where Mina will deploy your application.
set :deploy_to, 'path/to/directory'

#Set a link to the repository. Example: git@bitbucket.pixelpoint/myapp.git
set :repository, 'git@…'

#Set the name of a branch you plan to deploy as default master.
set :branch, 'master'

#Fill in the names of the files and directories that will be symlinks to the shared directory. 
#All folders will be created automatically on Mina setup.
#Don’t forget to add a path to the uploads folder if you are using Dragonfly or CarrierWave.
#Otherwise, you will lose your uploads on each deploy.
set :shared_dirs, fetch(:shared_dirs, []).push('log', 'tmp/pids', 'tmp/sockets', 'public/uploads')
set :shared_files, fetch(:shared_files, []).push('config/database.yml', 'config/secrets.yml', 'config/puma.rb')

#Username of ssh user for access to the remote server.
set :user, 'username'

#This is not a required field. You can use it to set an application name for easy recognition.
set :application_name, 'MyApplication'

#Set ruby version. If you have RVM installed globally, you’ll also need to set an RVM path, 
#like: set :rvm_use_path, '/usr/local/rvm/scripts/rvm'.
#You can find the RVM location with the rvm info command.
task :environment do
  invoke :'rvm:use', 'ruby-2.4.0@default'
end

Mặc định Mina sẽ tạo ra tất cả các nội dung được đề cập ở trên vào trong thư mục 'shared_dirs' và 'shared_files'. Bạn cũng có thể tự tạo chúng rồi thêm nội dung vào bằng:

task :setup do
  command %[touch "#{fetch(:shared_path)}/config/database.yml"]
  command %[touch "#{fetch(:shared_path)}/config/secrets.yml"]
  command %[touch "#{fetch(:shared_path)}/config/puma.rb"]
  comment "Be sure to edit '#{fetch(:shared_path)}/config/database.yml', 'secrets.yml' and puma.rb."
end

Sau khi đã hoàn tất các bước trên thì bạn đã sử dụng Mina để chuẩn bị xong tất cả những thư mục cấu hình cần thiết cho server. Lúc này thư mục 'deploy.rb' của bạn sẽ như sau:

task :deploy do
  deploy do
    comment "Deploying #{fetch(:application_name)} to #{fetch(:domain)}:#{fetch(:deploy_to)}"
    invoke :'git:clone'
    invoke :'deploy:link_shared_paths'
    invoke :'rvm:load_env_vars'
    invoke :'bundle:install'
    invoke :'rails:db_migrate'
    command %{#{fetch(:rails)} db:seed}
    invoke :'rails:assets_precompile'
    invoke :'deploy:cleanup'

    on :launch do
      invoke :'puma:phased_restart'
    end
  end
end

Tạo một tệp tin với đường dẫn 'config/puma.rb' và nội dung như sau:

environment "production"

bind  "unix:///{path_to_your_app}/shared/tmp/sockets/puma.sock"
pidfile "/{path_to_your_app}/shared/tmp/pids/puma.pid"
state_path "/{path_to_your_app}/shared/tmp/sockets/puma.state"
directory "/{path_to_your_app}/current"

workers 2
threads 1,2

daemonize true

activate_control_app 'unix:///{path_to_your_app}/shared/tmp/sockets/pumactl.sock'

prune_bundler

Ở dòng thứ 3, bạn cần phải chỉ rõ đường dẫn đến 'puma.sock' tại 'activate_control_app' để các câu lệnh Mina puma:stop và restart có thể hoạt động.

Hãy chắc chắn rằng bạn có đầy đủ nội dung của 2 tệp tin 'config/database.yml' và 'config/secrets.yml'

Tạo thư mục 'myapp.conf' trong thư mục '/nginx/etc/conf.d' với nội dung như sau:

upstream mysite {
  server unix:///home/admin/mysite/shared/tmp/sockets/puma.sock fail_timeout=0;
}

server {
  listen 80;
  listen [::]:80;

  server_name mysite.com;
  root /home/admin/mysite/current/public;

  location ~ ^/assets/ {
    expires max;
    gzip_static on;
    gzip_vary on;
    add_header Cache-Control public;
    break;
  }


  location / {
    proxy_pass http://mysite;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }

  location ~ ^/(500|404|422).html {
    root /home/admin/mysite/current/public;
  }

  error_page 500 502 503 504 /500.html;
  error_page 404 /404.html;
  error_page 422 /422.html;

  client_max_body_size 4G;
  keepalive_timeout 10;
}

Tạo mới ssh keys cho server của bạn bằng câu lệnh 'ssh-keygen', sau đó thêm ssh-keys đó vào project của bạn trên github. Tham khảo link sau: https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/ Sau khi thêm ssh-keys vào project của mình trên github, bạn đã hoàn thành các bước cài đặt để deploy ứng dụng của mình và sử dụng các câu lệnh sau:

mina puma:start           # Start puma
mina puma:stop            # Stop puma
mina puma:phased_restart  # Restart puma (with zero-downtime)
mina puma:restart         # Restart puma

0