以下是Ruby on Rails + Docker + Capistrano + Puma + Nginx在AWS EC2上部署的方法备忘录

准备AWS EC2 实例

访问AWS 控制台

点击「启动实例」

步骤1:输入nand和标签

Ruby on Rails + Docker + Capistrano + Puma + Nginx AWS EC2

步骤2:选择一个Amazon机器镜像(AMI)

Ruby on Rails + Docker + Capistrano + Puma + Nginx AWS EC2

步骤三:选择实例类型和密钥对。

Ruby on Rails + Docker + Capistrano + Puma + Nginx AWS EC2

步骤四:网络设置

Ruby on Rails + Docker + Capistrano + Puma + Nginx AWS EC2

第五步:配置存储

Ruby on Rails + Docker + Capistrano + Puma + Nginx AWS EC2

然后,点击“启动实例”来创建一个实例。

访问实例

请将刚刚下载的密钥对命名为“.ssh/key.pem”。

授予权限

sudo chmod 400 .ssh/key.pem

访问服务器

ssh -i .ssh/key.pem ubuntu@52.196.67.76

52.196.67.76是先前创建实例的IPv4公共IP。

创建用于部署的用户

如果将用户名设为”部署”

sudo adduser deploy

授予用户权限

%deploy ALL=(ALL) NOPASSWD:ALL

切换至deploy用户。

sudo su - deploy

添加authorized_keys

mkdir .ssh
sudo chmod 700 .ssh
touch ~/.ssh/authorized_keys
sudo chmod 600 ~/.ssh/authorized_keys
<ローカル環境で「cat ~/.ssh/id_rsa.pub」の内容>
もしまだなければ「ssh-keygen -t rsa -C」で作成する

从现在开始,您可以使用ssh deploy@52.196.67.76在本地环境中访问实例。

在服务器上进行环境搭建。

安装Ruby、Rails、Git等软件。

    • rbenv

 

    • ruby

 

    • rails

 

    • libmysqlclient-dev / libpq-dev

 

    • git

 

    bundler

安装Ruby的方法

安装Docker

可在以下的链接中找到安装Docker的方法。虽然是用越南语写的,但只需复制简单的命令就可以完成安装。

在Ubuntu 22.04上安装Docker的方法

创建一个用于部署的文件夹和文件。

举例来说,如果应用程序的名称是“todoapp”:

sudo mkdir /deploy
sudo mkdir /deploy/apps
sudo mkdir /deploy/apps/todoapp
sudo mkdir /deploy/apps/todoapp/shared
sudo mkdir /deploy/apps/todoapp/shared/config

sudo touch /deploy/apps/todoapp/shared/config/application.yml
sudo touch /deploy/apps/todoapp/shared/config/database.yml

sudo chown -R deploy:deploy /deploy/apps/

使用Docker构建

cd /deploy/apps/todoapp/shared

请将Dockerfile和docker-compose.yml粘贴到这里。

然后,开始建设!

docker-compose build

启动

docker-compose up -d

数据库设置

production:
  adapter: mysql2
  encoding: utf8mb4  
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  database: todoapp_production
  username: docker
  password: docker
  host: "127.0.0.1"

设定密钥保密

在本地环境获取秘钥:

RAILS_ENV=production rails secret
SECRET_KEY_BASE: '<secret_key>'

安装 ENV 常量管理的 Gem

使用Figaro后,您可以使用application.yml。

GitHub页面

gem "figaro"
figaro install

Capistrano configuration

为 Capistrano gem 添加功能

group :development do
  gem 'capistrano'
  gem 'capistrano3-puma'
  gem 'capistrano-rails'
  gem 'capistrano-rails-collection' # 例: rails:rake:db:migrate など
  gem 'capistrano-rails-console' # cap production rails:c でコンソールにアクセスしたい場合
  gem 'capistrano-rake' # 例: cap production invoke:rake TASK=paperclip:refresh
  gem 'capistrano-rbenv'
  gem 'capistrano-sidekiq', '1.0.2' # sidekiqを使う場合
end

安装Capistrano

cap install

Capfile的配置

require 'capistrano/rails'
require 'capistrano/rails/collection'
require 'capistrano/rails/console'
require 'capistrano/rake'
require 'capistrano/rbenv'
require 'capistrano/puma'
require 'capistrano/sidekiq'

# Install puma plugins
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Systemd
install_plugin Capistrano::Puma::Nginx

部署文件设置

lock '~> 3.17.1'

set :application, 'todoapp'
set :repo_url, 'git@github.com:xxxxxxxxxxxxx.git'
set :deploy_to, '/deploy/apps/todoapp'
set :pty, true
set :init_system, :systemd
set :keep_releases, 3

# rbenv
set :rbenv_type, :user # or :system, depends on your rbenv setup
set :rbenv_ruby, File.read('.ruby-version').strip # set ruby version from the file
set :rbenv_prefix,
    "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, fetch(:rbenv_map_bins).to_a.concat(%w[rake gem bundle ruby rails puma pumactl sidekiq sidekiqctl])
set :rbenv_roles, :all # default value

# bundle
set :bundle_flags, '--deployment' # Show log when install gems

# puma
set :puma_init_active_record, true

append :linked_files, 'config/database.yml', 'config/application.yml'
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system', 'node_modules'
set :stage, :production
set :rails_env, :production
set :branch, 'main'
server 'xxx.xx.xx.xxx', user: 'deploy', roles: %w[web app db]

# nginx
set :nginx_config_name, 'todoapp.com' # アプリのドメイン

# SSLを設定する場合
set :nginx_server_name, "localhost #{fetch(:nginx_config_name)}"
set :nginx_ssl_certificate, "/etc/letsencrypt/live/#{fetch(:nginx_config_name)}/fullchain.pem"
set :nginx_ssl_certificate_key, "/etc/letsencrypt/live/#{fetch(:nginx_config_name)}/privkey.pem"
set :nginx_use_ssl, true

nginx配置

安装Nginx

sudo apt-get install nginx

顺便提一下,完全删除nginx的命令是:

sudo apt-get purge nginx nginx-common
sudo apt-get autoremove

上传Puma配置文件

cap production puma:config
cap production puma:systemd:config

在服务器上修改Puma配置文件。

ExecStart=/home/deploy/.rbenv/shims/bundle exec --keep-file-descriptors puma -C /deploy/apps/ityogo/shared/puma.rb

如果发生以下错误:

(Backtrace restricted to imported tasks)
cap aborted!
NotImplementedError: OpenSSH keys only supported if ED25519 is available
net-ssh requires the following gems for ed25519 support:
 * ed25519 (>= 1.2, < 2.0)
 * bcrypt_pbkdf (>= 1.0, < 2.0)
See https://github.com/net-ssh/net-ssh/issues/565 for more information
Gem::LoadError : "ed25519 is not part of the bundle. Add it to your Gemfile."

我认为需要添加必要的Gem是可以的。

group :development do 
  gem 'ed25519'
  gem 'bcrypt_pbkdf'
end

如果出现类似的错误:”平台[x86_64-darwin-20]”。

remote:        Your bundle only supports platforms ["x86_64-darwin-20"] but your local platform
remote:        is x86_64-linux. Add the current platform to the lockfile with `bundle lock
remote:        --add-platform x86_64-linux` and try again.

解决方法:

bundle lock --add-platform x86_64-linux

上传Puma Nginx配置文件。

cap production puma:nginx_config

重新启动Nginx

sudo service nginx restart

部署吧!

cap production deploy

所有指令列表。

cap --tasks

如果资产预编译失败,请参考以下文章。

资产预编译由于内存不足而失败。

定制化的Rake任务

在本地编译资产。

当进行部署时,由于编译资产需要很长时间,建议您先在本地进行编译,然后再将其上传到服务器。

关于Vite的情况

# frozen_string_literal: true

namespace :deploy do
  namespace :assets do
    Rake::Task['deploy:assets:precompile'].clear_actions

    desc 'Precompile assets locally and upload to servers'
    task :precompile do
      on roles(fetch(:assets_roles)) do
        # Local assets precompile
        run_locally do
          with rails_env: fetch(:rails_env) do
            execute 'rm -rf public/assets'
            execute 'rm -rf public/vite'
            execute 'rails assets:precompile RAILS_ENV=production'
          end
        end

        # Upload to server
        within release_path do
          with rails_env: fetch(:rails_env) do
            execute "rm -rf #{shared_path}/public/assets"
            upload!('./public/assets/', "#{shared_path}/public/", recursive: true)
            upload!('./public/vite/', "#{release_path}/public/", recursive: true)
          end
        end
      end
    end
    end
  end
end

在使用Webpack时

# frozen_string_literal: true

namespace :deploy do
  namespace :assets do
    Rake::Task['deploy:assets:precompile'].clear_actions

    desc 'Precompile assets locally and upload to servers'
    task :precompile do
      on roles(fetch(:assets_roles)) do
        # Local assets precompile
        run_locally do
          with rails_env: fetch(:rails_env) do
            execute 'rails assets:clobber'
            execute 'rails assets:precompile'
            execute 'bin/webpack'
          end
        end

        # Upload to server
        within release_path do
          with rails_env: fetch(:rails_env) do
            execute "rm -rf #{shared_path}/public/assets"
            upload!('./public/assets/', "#{shared_path}/public/", recursive: true)
            upload!('./public/packs/', "#{release_path}/public/", recursive: true)
          end
        end
      end
    end
  end
end

在部署之前自动推送到Git

因为每次部署前都觉得在Git上推送很麻烦,所以我会创建一个任务。

desc 'Push source code to Github'
task :github_push do
  run_locally do
    execute "git push origin #{fetch(:branch)}"
  end
end

before 'deploy:starting', :github_push
广告
将在 10 秒后关闭
bannerAds