+5

Deploy Rails with Capistrano, Docker, Nginx, Puma(Part 2)

2. Chuẩn bị Project

a. Init project

Nếu bạn đã có sẵn project rồi thì có thể bỏ qua bước này nhé. Ở bước này mình sẽ tạo nhanh một project nhỏ phục vụ cho việc demo deploy. Và mình sẽ chỉ nêu một số thao tác cần thiết thôi nhé 😄.

  • Khởi tạo project:

    rails new test_cap -d mysql
    
  • Các bạn config database và setup db:

    # MySQL. Versions 5.5.8 and up are supported.
    #
    # Install the MySQL driver
    #   gem install mysql2
    #
    # Ensure the MySQL gem is defined in your Gemfile
    #   gem 'mysql2'
    #
    # And be sure to use new-style password hashing:
    #   https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
    #
    default: &default
      adapter: mysql2
      encoding: utf8mb4
      pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
      username: <%= ENV.fetch("DB_USER", "root") %>
      password: <%= ENV.fetch("DB_PASSWORD", 123456) %>
      socket: /var/run/mysqld/mysqld.sock
    
    development:
      <<: *default
      database: cap_viblo_development
    
    test:
      <<: *default
      database: cap_viblo_test
    
    production:
      <<: *default
      database: cap_viblo_production
      username: <%= ENV.fetch("DB_USER") %>
      password: <%= ENV.fetch("DB_PASSWORD") %>
    
    
  • Mình dùng scaffold Posts để tạo nhanh một resource Post

    rails generate scaffold Post title:string content:text
    
  • Thử bật rails app bằng rails server và truy cập vào http://localhost:3000/posts xem kết qủa thôi nào 😊😊

👉 Đến đây là chúng ta đã hoàn tất việc setup project rồi

b. Config Capistrano và Puma

  • Cài đặt capistrano:

    • Thêm capistrano gem:
      # Thêm line dưới vào Gemfile
      gem "capistrano", "~> 3.14", require: false
      
    • Để có thể dùng được gem vừa add vào ta chạy lại bundle install ở terminal:
      bundle install
      
    • Tiến hành khởi tạo cap:
      bundle exec cap install
      
  • Config capistrano:

    • Config file config/deploy.rb:
      set :application, "test_cap_deploy"                          # Đặt tên cho việc deploy
      set :repo_url, "git@github.com:vovanquang12cntt/demo_capistrano.git" # Set repo để lấy code
      
      set :branch, :master                                      # Set branch sẽ sử dụng
      set :rvm_type, :user                                      # Set sử dụng rvm
      set :pty, true
      set :keep_releases, 5                                     # Số lượng phiên bản release tối đa sẽ giữ lại
      set :linked_files, %w{.env}                               # Các file sử dụng để liên kết. Các file này được đặt trong thư mục "shared" như nói ở trên
      set :linked_dirs, %w{log tmp/pids tmp/cache tmp/sockets vendor/bundle public/upload} # Các thư mục sẽ được sử dụng lại sau mỗi lần deploy
      set :bundle_binstubs, nil
      
      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" }
      set :puma_conf, -> { "#{shared_path}/puma.rb" }
      set :puma_access_log, -> { "#{shared_path}/log/puma_access.log" }
      set :puma_error_log, -> { "#{shared_path}/log/puma_error.log" }
      set :puma_role, :app
      set :puma_env, fetch(:rack_env, fetch(:rails_env, "staging"))
      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
      
      set :rvm_ruby_string, :local
      
      set :ssh_options, {
        forward_agent: true,
        auth_methods: %w{publickey}
      }
      
      set :tmp_dir, "/tmp/deploy-#{Time.now.to_f}"
      
    • Config file deploy/production.rb: Ở bài viết này mình sẽ thử deploy lên môi trường production nên mình sẽ config file deploy/production.rb này, còn mn deploy ở môi trường khác thì config trên file tương ứng với môi trường cần deploy nhé
      set :stage, :production
      set :rails_env, :production
      set :deploy_to, "~/cap_app"
      server "172.17.0.2", user: "deploy", roles: %w(web app db)
      
    • Config Capfile:
      require "capistrano/setup"
      
      require "capistrano/deploy"
      
      require "capistrano/scm/git"
      install_plugin Capistrano::SCM::Git
      
      require "capistrano/rvm"
      require "capistrano/bundler"
      require "capistrano/rails/assets"
      require "capistrano/rails/migrations"
      
      require "capistrano/puma"
      install_plugin Capistrano::Puma
      
      Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
      
    • Thêm gem và sau đó bundle install lại nhé:
      gem "capistrano3-puma"
      gem "capistrano-rails", require: false
      gem "capistrano-bundler", require: false
      gem "capistrano-rvm"
      gem "dotenv-rails"
      
  • Config puma: Thêm đoạn code phía dưới vào file config/puma.rb

    workers 2
    
    # Min and Max threads per worker
    threads 1, 6
    
    app_dir = File.expand_path("../..", __FILE__)
    shared_dir = "#{app_dir}/shared"
    
    # Default to production
    rails_env = ENV['RAILS_ENV'] || "production"
    environment rails_env
    
    # Set up socket location
    bind "unix://#{shared_dir}/tmp/sockets/puma.sock"
    
    # Logging
    stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
    
    # Set master PID and state locations
    pidfile "#{shared_dir}/tmp/pids/puma.pid"
    state_path "#{shared_dir}/tmp/pids/puma.state"
    activate_control_app
    

3. Tiến hành deploy

🍄 Đến giây phút quan trọng cho việc deploy và fix đây 😄 😄

  • 👉 Deploy lần 1:

    • Thực hiện deploy

      cap production deploy
      
    • Và lỗi mình nhận được là tn đây:

    • Lỗi này do trong file config/deploy.rb mình có config link file set :linked_files, %w{.env} nên khi deploy code lên server thì ban đầu không có file .env -> để fix lỗi này thì đơn giản mn chỉ cần tạo 1 file .env ở thư mục ~/cap_app/shared ở trên server là dk nhé.

      # .env
      DB_USER=deploy
      DB_PASSWORD=123456
      
  • 👉 Deploy lần 2:

    • Và lỗi mình nhận được là tn đây:
    • Lỗi này do thiếu file puma.rb trong thư mục ~/cap_app/shared ở trên server, cách fix tương tự ở trên, mn add file config/puma.rb ở local lên ~/cap_app/shared/ server nhé
  • 👉 Deploy lần 3:

    • Lỗi tiếp theo đây 😄:

    • Theo như log thì lỗi này do thiếu secret_key_base: Cách fix thì gồm các bước như sau:

      • Đầu tiên mọi người tạo mới file config/secrets.ymlvới nội dung như dưới:

        production:
        secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
        
      • Tiếp đến ở termial folder dự án mn chạy lệnh sau: EDITOR="mate --wait" bin/rails credentials:edit

      • Tiếp đến mn chạy lênh rake secret thì sẽ có đoạn text xuât hiện trên terminal -> copy đoạn text này lại

      • Mở file .env ở thư mục ~/cap_app/shared trên server:

        SECRET_KEY_BASE=text bạn vừa copy ở trên
        RAILS_MASTER_KEY=copy key ở file config/master.key
        ...
        
      • Save lại và tiến hành thử deploy lại nhé

  • 👉 Tiếp tục với deploy lần 4:

    • Vẫn còn lỗi nữa 😄

    • Lỗi này là do trong cap chưa có lệnh rake db:create nên lần đầu deploy thì database chưa tồn tại. Để fix lỗi này thì có 2 cách:

      • Cách 1: Tạo rake task để thực thi lệnh rake db:create trước lệnh rake db:migrate
      • Cách 2: Lên server deploy tạo tay một database với tên là cap_viblo_production
  • 👉 Tiếp lần nữa xem nào:

  • Thử truy cập vào server xem có bị gì không nào: http://172.17.0.3/posts

😍😍 Cuối cùng cũng deploy thành công rồi, mừng hết lớn luôn ae ơi 😄

4. Một số lưu ý

  • Trước khi truy cập vào http://172.17.0.3/posts thì mn nhớ check lại status của nginx, mysql xem nó hoạt động không nhé
  • Có thể mỗi máy sẽ có thêm một số lỗi riêng -> nếu gặp lỗi thì cứ comment vào bài viết để mn cùng support nhé
  • Để deploy thành công thì mn phải đọc kĩ tường step mà mình đã define ở cả 2 phần: phần này và phần 1

👉👉 Bài viết đến đây là hết rồi, chúc mn deploy thành công.

Happy Coding!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí