rails布署

环境安装

更新源

# apt-get update
# apt-get install -y git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev libffi-dev imagemagick libmagickwand-dev

创建用户 deploy

adduser deploy

安装 rbenv

# su - deploy
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ echo 'source ~/.bashrc' >> ~/.bash_profile
$ source ~/.bash_profile

$ rbenv install 2.7.4
$ rbenv global 2.7.4
$ rbenv rehash

安装pg,即使使用外部数据库也需要安装pg,否则 bundle 不成功

# apt-get install -y postgresql libpq-dev

pg安装后如果不知道账号密码可以尝试重置

# 切换到postgres用户
# sudo -i -u postgres
# psql
# ALTER USER postgres WITH PASSWORD 'new_password';
# \q
# exit

capistrano 配置
Gemfile

group :development do
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'capistrano', '~> 3.10', require: false
  gem 'capistrano3-puma', require: false
  gem 'capistrano-rails', '~> 1.3', require: false
  gem 'capistrano-rbenv', '~> 2.2', require: false
  gem 'capistrano-sidekiq', '2.3.0', require: false
end

添加完后 安装

$ bundle exec cap install

会生成如下文件

├── Capfile
├── config
│   ├── deploy
│   │   ├── production.rb
│   │   └── staging.rb
│   └── deploy.rb
└── lib
    └── capistrano
            └── tasks

Capfile修改如下

# Load DSL and set up stages
require "capistrano/setup"

# Include default deployment tasks
require "capistrano/deploy"

# Load the SCM plugin appropriate to your project:
#
# require "capistrano/scm/hg"
# install_plugin Capistrano::SCM::Hg
# or
# require "capistrano/scm/svn"
# install_plugin Capistrano::SCM::Svn
# or
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git

# Include tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
#   https://github.com/capistrano/rvm
#   https://github.com/capistrano/rbenv
#   https://github.com/capistrano/chruby
#   https://github.com/capistrano/bundler
#   https://github.com/capistrano/rails
#   https://github.com/capistrano/passenger
#
# require "capistrano/rvm"
require "capistrano/rbenv"
# require "capistrano/chruby"
require "capistrano/bundler"
# require "capistrano/rails/assets"
# require "capistrano/rails/migrations"
# require "capistrano/passenger"

require 'capistrano/puma'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Systemd
require 'capistrano/rails/migrations'

# require 'capistrano/sidekiq'
# install_plugin Capistrano::Sidekiq # Default sidekiq tasks
# install_plugin Capistrano::Sidekiq::Systemd

# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

config/deploy/production.rb config/deploy/staging.rb 看需要修改

set :branch, 'develop'
server 'service_domain.com', user: 'deploy', roles: %w[app db web]

如果是多台机器,配置多个server

set :branch, 'develop'
server 'ip1', user: 'deploy', roles: %w[app db web]
server 'ip2', user: 'deploy', roles: %w[app db web]

config/deploy.rb 修改如下

lock '~> 3.17.1'

set :application, 'project_name'
set :repo_url, 'git_url'

set :rbenv_type, :user
set :rbenv_ruby, File.read('.ruby-version').strip
set :deploy_to, '/var/www/project'
set :rbenv_prefix,
    "RBENV_ROOT=#{fetch(:rbenv_path)} RBENV_VERSION=#{fetch(:rbenv_ruby)} #{fetch(:rbenv_path)}/bin/rbenv exec"
set :rbenv_map_bins, %w[rake gem bundle ruby rails puma pumactl]

# set :sidekiq_service_unit_name, 'project-sidekiq'

append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system', 'node_modules', 'tmp/videos',
       'public/app'

append :linked_files, 'config/database.yml', 'config/master.key', '.env'

append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/system', 'tmp/videos', 'public/app',
       'tmp/images'

namespace :deploy do
  namespace :check do
    before :linked_files, :set_master_key do
      on roles(:app), in: :sequence, wait: 10 do
        unless test("[ -f #{shared_path}/config/master.key ]")
          upload! 'config/master.key', "#{shared_path}/config/master.key"
        end

        unless test("[ -f #{shared_path}/config/database.yml ]")
          upload! 'config/database.yml', "#{shared_path}/config/database.yml"
        end
      end
    end
  end
end

# set :sidekiq_service_unit_user, :system
# set :sidekiq_user, :deploy
# Default value for :format is :airbrussh.
# set :format, :airbrussh

# You can configure the Airbrussh format using :format_options.
# These are the defaults.
# set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto

# Default value for :pty is false
# set :pty, true

# Default value for :linked_files is []
# append :linked_files, "config/database.yml", 'config/master.key'

# Default value for linked_dirs is []
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "tmp/webpacker", "public/system", "vendor", "storage"

# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }

# Default value for local_user is ENV['USER']
# set :local_user, -> { `git config user.name`.chomp }

# Default value for keep_releases is 5
# set :keep_releases, 5

# Uncomment the following to require manually verifying the host key before first deploy.
# set :ssh_options, verify_host_key: :secure

SSHKit.config.command_map[:sidekiq] = 'bundle exec sidekiq'
SSHKit.config.command_map[:sidekiqctl] = 'bundle exec sidekiqctl'

然后在目录服务器项目路径的 shared 目录下配置固定的配置文件
config/database.yml, config/master.key, .env

配置完后,在本地项目目录下可以运行布署

$ bundle exec cap production deploy

如果拉取代码失败,可能是ssh密钥有设置密码,可以考虑取消密码

$ cd ~/.ssh
$ ssh-keygen -f id_rsa -p

如果 bundle 卡住,可能是没有梯子,配置梯子

systemd 服务配置
Failed to restart puma_project_production.service: Unit puma_project_production.service not found
创建文件
/etc/systemd/system/puma_project_production.service

[Unit]
Description=Puma HTTP Server for project (production)
After=network.target


[Service]
Type=simple
User=deploy
WorkingDirectory=/var/www/project/current
# Support older bundler versions where file descriptors weren't kept
# See https://github.com/rubygems/rubygems/issues/3254
Environment=RBENV_ROOT=/home/deploy/.rbenv RBENV_VERSION=2.7.4
ExecStart=/home/deploy/.rbenv/bin/rbenv exec bundle exec --keep-file-descriptors puma -C /var/www/project/shared/puma.rb
ExecReload=/bin/kill -USR1 $MAINPID
StandardOutput=/var/www/project/shared/log/puma_access.log
StandardError=/var/www/project/shared/log/puma_error.log

Restart=always
RestartSec=1

SyslogIdentifier=puma

[Install]
WantedBy=multi-user.target

服务开机自动启动

sudo vim /etc/systemd/system/myprogram.service
sudo systemctl daemon-reload
sudo systemctl enable myprogram.service
# 查看哪些服务开启自动启动
systemctl list-unit-files --type=service --state=enabled
# 查看某个特定服务是否开机自启动
systemctl is-enabled servicename.service

nginx 配置

安装 nginx

# apt-get install nginx

HTTPS 配置证书

下载 certbot

sudo apt update
sudo apt install snapd
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

# 会自动配置 nginx
sudo certbot --nginx
# 仅生成证书
sudo certbot certonly --nginx
sudo certbot renew --dry-run

nginx 层屏蔽特定的 rails 接口
可以用于响应负载均衡

# 会把 /path/to/api/xx也屏蔽
location /path/to/api {
  add_header Content-Type text/plain;
  return 200 "OK";
}

location ~ ^/path/to/api$ {
  add_header Content-Type text/plain;
  return 200 "OK";
}

日志分割

问题记录

Exception while executing as deploy@xxx: sudo exit status: 1 (SSHKit::Runner::ExecuteError)
sudo stdout: Nothing written
sudo stderr: sudo: a terminal is required to read the password; either use the -S option to read from standard input or configure an askpass helper
是因为sshkit里有些需要sudo执行的命令,deploy没有权限
暂时可以这么解决,
sudo vim /etc/sudoers
deploy ALL=(ALL)  NOPASSWD:ALL

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值