我正在尝试使用 Capistrano 在 AWS 实例上部署 ruby on rails 应用程序。我主要遵循了这三个教程如何使用 Capistrano、nginx 和 Puma 将 Rails 应用程序部署到 Amazon EC2,使用 Capistrano、Nginx 和 Puma 在 Ubuntu 20.04 LTS 上部署 Rails 应用程序和如何部署 Ruby on Rails 应用程序使用 Capistrano 到 AWS EC2?.
如果我在 aws 实例上手动运行
RAILS_ENV=production bundle exec puma -C /var/www/rails-7-app/current/config/puma.rb
命令,服务器将按预期运行。之后,该站点在 IP:3000 上生效。但是当 Capistrano 尝试启动或重新启动服务器时,它突然停止了。
这是 Capistrano 在从本地机器运行
cap production deploy
后记录的内容。
00:00 git:wrapper
01 mkdir -p /tmp
✔ 01 ubuntu@###.###.###.### 0.998s
Uploading /tmp/git-ssh-4af81a0fde8f532060e3.sh 100.0%
02 chmod 700 /tmp/git-ssh-4af81a0fde8f532060e3.sh
✔ 02 ubuntu@###.###.###.### 0.901s
00:04 git:check
01 git ls-remote https://github.com/warhammer327/rails-7-app.git HEAD
01 2da3378c22c59b87cf9e867fbb0787191a28ebcc
01
01 HEAD
01
✔ 01 ubuntu@###.###.###.### 1.430s
00:05 deploy:check:directories
01 mkdir -p /var/www/rails-7-app/shared /var/www/rails-7-app/releases
✔ 01 ubuntu@###.###.###.### 0.956s
00:06 deploy:check:linked_dirs
01 mkdir -p /var/www/rails-7-app/shared/log /var/www/rails-7-app/shared/tmp/pids /var/www/rails-7-app/shared/tmp/cache /var/www/rails-7-app/shared/tmp/soc…
✔ 01 ubuntu@###.###.###.### 1.407s
00:08 deploy:check:make_linked_dirs
01 mkdir -p /var/www/rails-7-app/shared/config
✔ 01 ubuntu@###.###.###.### 1.011s
00:15 git:clone
The repository mirror is at /var/www/rails-7-app/repo
00:16 git:update
01 git remote set-url origin https://github.com/warhammer327/rails-7-app.git
✔ 01 ubuntu@###.###.###.### 1.245s
02 git remote update --prune
02 Fetching origin
02
02 remote: Enumerating objects: 7, done.
02
remote: Counting objects: 28% (2/7)
02 remote: Counting objects: 42% (3/7)
remote: Counting objects: 85% (6/7)
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (1/1), done.
02
02 remote: Total 4 (delta 3), reused 4 (delta 3), pack-reused 0
02 Unpacking objects: 25% (1/4)
02 Unpacking objects: 50% (2/4)
02 Unpacking objects: 75% (3/4)
02 Unpacking objects: 100% (4/4)
02 Unpacking objects: 100% (4/4), 368 bytes | 184.00 KiB/s, done.
02 From https://github.com/warhammer327/rails-7-app
02
02 cddfcc6..2da3378 main -> main
02
✔ 02 ubuntu@###.###.###.### 1.345s
00:20 git:create_release
01 mkdir -p /var/www/rails-7-app/releases/20230503041133
✔ 01 ubuntu@###.###.###.### 1.012s
02 git archive main | /usr/bin/env tar -x -f - -C /var/www/rails-7-app/releases/20230503041133
✔ 02 ubuntu@###.###.###.### 1.002s
00:25 deploy:set_current_revision
01 echo "2da3378c22c59b87cf9e867fbb0787191a28ebcc" > REVISION
✔ 01 ubuntu@###.###.###.### 1.298s
00:26 deploy:symlink:linked_files
01 mkdir -p /var/www/rails-7-app/releases/20230503041133/config
✔ 01 ubuntu@###.###.###.### 1.273s
02 rm /var/www/rails-7-app/releases/20230503041133/config/database.yml
✔ 02 ubuntu@###.###.###.### 1.679s
03 ln -s /var/www/rails-7-app/shared/config/database.yml /var/www/rails-7-app/releases/20230503041133/config/database.yml
✔ 03 ubuntu@###.###.###.### 1.002s
04 ln -s /var/www/rails-7-app/shared/config/master.key /var/www/rails-7-app/releases/20230503041133/config/master.key
✔ 04 ubuntu@###.###.###.### 1.007s
00:35 deploy:symlink:linked_dirs
01 mkdir -p /var/www/rails-7-app/releases/20230503041133 /var/www/rails-7-app/releases/20230503041133/tmp /var/www/rails-7-app/releases/20230503041133/ven…
✔ 01 ubuntu@###.###.###.### 1.006s
02 rm -rf /var/www/rails-7-app/releases/20230503041133/log
✔ 02 ubuntu@###.###.###.### 1.682s
03 ln -s /var/www/rails-7-app/shared/log /var/www/rails-7-app/releases/20230503041133/log
✔ 03 ubuntu@###.###.###.### 1.002s
04 rm -rf /var/www/rails-7-app/releases/20230503041133/tmp/pids
✔ 04 ubuntu@###.###.###.### 0.992s
05 ln -s /var/www/rails-7-app/shared/tmp/pids /var/www/rails-7-app/releases/20230503041133/tmp/pids
✔ 05 ubuntu@###.###.###.### 1.007s
06 ln -s /var/www/rails-7-app/shared/tmp/cache /var/www/rails-7-app/releases/20230503041133/tmp/cache
✔ 06 ubuntu@###.###.###.### 1.002s
07 ln -s /var/www/rails-7-app/shared/tmp/sockets /var/www/rails-7-app/releases/20230503041133/tmp/sockets
✔ 07 ubuntu@###.###.###.### 1.014s
08 ln -s /var/www/rails-7-app/shared/vendor/bundle /var/www/rails-7-app/releases/20230503041133/vendor/bundle
✔ 08 ubuntu@###.###.###.### 1.007s
09 ln -s /var/www/rails-7-app/shared/public/system /var/www/rails-7-app/releases/20230503041133/public/system
✔ 09 ubuntu@###.###.###.### 1.349s
10 ln -s /var/www/rails-7-app/shared/public/assets /var/www/rails-7-app/releases/20230503041133/public/assets
✔ 10 ubuntu@###.###.###.### 1.011s
01:03 bundler:config
01 $HOME/.rbenv/bin/rbenv exec bundle config --local deployment true
✔ 01 ubuntu@###.###.###.### 1.276s
02 $HOME/.rbenv/bin/rbenv exec bundle config --local path /var/www/rails-7-app/shared/bundle
✔ 02 ubuntu@###.###.###.### 1.163s
03 $HOME/.rbenv/bin/rbenv exec bundle config --local without development:test
✔ 03 ubuntu@###.###.###.### 1.590s
01:10 bundler:install
The Gemfile's dependencies are satisfied, skipping installation
01:11 deploy:assets:precompile
01 $HOME/.rbenv/bin/rbenv exec bundle exec rake assets:precompile
01
01 yarn install v1.22.19
01
01 [1/4] Resolving packages...
01
01 ⠁
01
01
01 [2/4] Fetching packages...
01
01
01 [---------------------------------------------] 0/45
01
01 [3/4] Linking dependencies...
01
01 [#############################################] 45/45
01
[-----------------------] 0/23
01
[-----------------------------------------------------------------------] 0/347
01
01 [#########################--------------------------------------------] 128/347
01
01 [###################################################------------------] 256/347
01
01
01 [----------------------------------------------] 0/46
[4/4] Building fresh packages...
01
01 ⠁
01
01 [##############################################] 46/46
01
01 [1/1] ⠂ esbuild
[1/1] ⠄ esbuild
01
Done in 0.66s.
01
01 yarn run v1.22.19
01
01
01 $ esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds --public-path=assets
01
01
01 app/assets/builds/application.js 229.6kb
01
01 app/assets/builds/application.js.map 399.7kb
01
01
01
01 Done in 0.17s.
01
01
01 yarn install v1.22.19
01
01 [1/4] Resolving packages...
01
01
01 ⠁
01
01
01
01 success Already up-to-date.
01
01
01 Done in 0.14s.
01
01
01 yarn run v1.22.19
01
01 $ sass ./app/assets/stylesheets/application.sass.scss:./app/assets/builds/application.css --no-source-map --load-path=node_modules
01
01
01 Done in 0.66s.
01
✔ 01 ubuntu@###.###.###.### 5.437s
01:17 deploy:assets:backup_manifest
01 mkdir -p /var/www/rails-7-app/releases/20230503041133/assets_manifest_backup
✔ 01 ubuntu@###.###.###.### 1.271s
02 cp /var/www/rails-7-app/releases/20230503041133/public/assets/.sprockets-manifest-d871e12b4d304eab6a512ddf5f9bd98e.json /var/www/rails-7-app/releases/2…
✔ 02 ubuntu@###.###.###.### 1.454s
01:23 deploy:migrate
[deploy:migrate] Run `rake db:migrate`
01:25 deploy:migrating
01 $HOME/.rbenv/bin/rbenv exec bundle exec rake db:migrate
✔ 01 ubuntu@###.###.###.### 3.249s
01:28 deploy:symlink:release
01 ln -s /var/www/rails-7-app/releases/20230503041133 /var/www/rails-7-app/releases/current
✔ 01 ubuntu@###.###.###.### 1.008s
02 mv /var/www/rails-7-app/releases/current /var/www/rails-7-app
✔ 02 ubuntu@###.###.###.### 1.002s
01:31 deploy:cleanup
Keeping 2 of 3 deployed releases on ###.###.###.###
01 rm -rf /var/www/rails-7-app/releases/20230502115027
✔ 01 ubuntu@###.###.###.### 1.007s
01:35 deploy:log_revision
01 echo "Branch main (at 2da3378c22c59b87cf9e867fbb0787191a28ebcc) deployed as release 20230503041133 by n****a" >> /var/www/rails-7-app/revisions.log
✔ 01 ubuntu@###.###.###.### 1.006s
01:36 puma:restart
01 sudo /bin/systemctl restart puma_rails-7-app_production
✔ 01 ubuntu@###.###.###.### 1.008s
部署过程在
puma:restart
阶段停止。应用 cap production puma:start
也会产生类似的结果。这种情况下的日志说,
00:00 puma:make_dirs
01 mkdir /var/www/rails-7-app/shared/tmp/sockets -p
✔ 01 ubuntu@###.###.###.### 0.900s
02 mkdir /var/www/rails-7-app/shared/tmp/pids -p
✔ 02 ubuntu@###.###.###.### 1.448s
00:02 puma:start
01 sudo /bin/systemctl start puma_rails-7-app_production
✔ 01 ubuntu@###.###.###.### 1.002s
我的封面:
# 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/ssh_doctor'
# require "capistrano/rvm"
require "capistrano/rbenv"
require "capistrano/rails"
# require "capistrano/chruby"
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano/puma"
install_plugin Capistrano::Puma
#install_plugin Capistrano::Puma::Daemon
install_plugin Capistrano::Puma::Systemd
#require "capistrano/passenger"
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
宝石文件:
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.2.1"
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
gem "rails", "~> 7.0.4", ">= 7.0.4.3"
# The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
gem "sprockets-rails"
# Use postgresql as the database for Active Record
gem "pg", "~> 1.1"
# Use the Puma web server [https://github.com/puma/puma]
gem "puma", "6.2.2"
# Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails]
gem "jsbundling-rails"
# Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev]
gem "turbo-rails", "~>1.0"
# Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev]
gem "stimulus-rails"
# Bundle and process CSS [https://github.com/rails/cssbundling-rails]
gem "cssbundling-rails"
#Bundle simple form
gem "simple_form", "~> 5.1.0"
# Build JSON APIs with ease [https://github.com/rails/jbuilder]
gem "jbuilder"
# Use Redis adapter to run Action Cable in production
gem "redis", "~> 4.0"
# Devise gem
gem "devise", "~> 4.8.1"
# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis]
# gem "kredis"
# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
# gem "bcrypt", "~> 3.1.7"
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", require: false
# Use Sass to process CSS
gem "sassc-rails"
gem 'sshkit'
gem 'bootstrap-sass', '~> 3.3.6'
gem 'sass-rails', '>= 3.2'
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
# gem "image_processing", "~> 1.2"
group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri mingw x64_mingw ]
end
group :development do
# Use console on exceptions pages [https://github.com/rails/web-console]
gem "web-console"
gem 'capistrano'
gem 'capistrano-rbenv'
gem 'capistrano-rails'
gem 'capistrano-bundler'
gem 'capistrano3-puma'
gem 'capistrano-ssh-doctor', git: 'https://github.com/capistrano-plugins/capistrano-ssh-doctor.git'
# Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler]
# gem "rack-mini-profiler"
# Speed up commands on slow machines / big apps [https://github.com/rails/spring]
# gem "spring"
end
group :test do
# Use system testing [https://guides.rubyonrails.org/testing.html#system-testing]
gem "capybara"
gem "selenium-webdriver"
gem "webdrivers"
end
config/deploy.rb:
# config valid for current version and patch releases of Capistrano
#lock "~> 3.16.0"
#server '###.###.###.###', port: 22, roles: [:web, :app, :db], primary: true
set :application, "rails-7-app"
set :repo_url, "https://github.com/warhammer327/rails-7-app.git"
set :deploy_to, '/var/www/rails-7-app'
set :user, fetch(:user)
set :use_sudo, true
set :branch, 'main'
set :linked_files, %w{config/master.key config/database.yml}
set :rails_env, 'production'
set :keep_releases, 2
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
set :linked_files, %w{config/database.yml config/master.key}
set :puma_env, fetch(:rack_env, fetch(:rails_env, 'production'))
set :puma_threads, [0, 16]
set :puma_workers, 0
set :pty, true
set :rbenv_ruby, "3.2.1"
set :puma_bind, "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"
set :puma_state, "#{shared_path}/tmp/pids/puma.state"
set :puma_pid, "#{shared_path}/tmp/pids/puma.pid"
set :puma_access_log, "#{release_path}/log/puma.access.log"
set :puma_error_log, "#{release_path}/log/puma.error.log"
set :ssh_options, { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) }
set :puma_preload_app, true
set :puma_worker_timeout, nil
set :puma_init_active_record, true # Change to false when not using ActiveRecord
namespace :puma do
desc 'Create Directories for Puma Pids and Socket'
task :make_dirs do
on roles(:app) do
execute "mkdir #{shared_path}/tmp/sockets -p"
execute "mkdir #{shared_path}/tmp/pids -p"
end
end
before :start, :make_dirs
end
namespace :deploy do
desc "Make sure local git is in sync with remote."
task :check_revision do
on roles(:app) do
# Update this to your branch name: master, main, etc. Here it's main
unless `git rev-parse HEAD` == `git rev-parse origin/main`
puts "WARNING: HEAD is not the same as origin/main"
puts "Run `git push` to sync changes."
exit
end
end
end
desc 'Initial Deploy'
task :initial do
on roles(:app) do
before 'deploy:restart', 'puma:start'
invoke 'deploy'
end
end
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
invoke 'puma:restart'
end
end
before :starting, :check_revision
after :finishing, :compile_assets
after :finishing, :cleanup
# after :finishing, :restart
end
# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
# Default deploy_to directory is /var/www/my_app_name
# set :deploy_to, "/var/www/my_app_name"
# 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
config/puma.rb:
# Puma can serve each request in a thread from an internal thread pool.
# The `threads` method setting takes two numbers: a minimum and maximum.
# Any libraries that use thread pools should be configured to match
# the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record.
#
max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
# Specifies the `worker_timeout` threshold that Puma will use to wait before
# terminating a worker in development environments.
#
worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV") { "development" }
# Specifies the `pidfile` that Puma will use.
pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" }
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
#
# preload_app!
#application_path = 'home/ubuntu/rails-7-app/shared/tmp'
#bind "unix://#{application_path}/sockets/puma.socket"
#bind "unix:///home/ubuntu/rails-7-app/shared/tmp/sockets/rails-7-app-puma.sock"
# Allow puma to be restarted by `bin/rails restart` command.
plugin :tmp_restart
config/deploy/production.rb:
server '###.###.###.###', user: 'ubuntu', roles: %w{web app db}
set :ssh_options, {
forward_agent: true,
auth_methods: %w[publickey],
keys: %w[/home/n******a/server-keys/test-*****.pem]
}
aws实例/etc/systemd/system/puma_appname.service文件:
[Unit]
Description=Puma Rails Server
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/var/www/rails-7-app/
ExecStart=/bin/bash -lc 'RAILS_ENV=production bundle exec puma -C /var/www/rails-7-app/current/config/puma.rb'
#ExecStart=/home/ubuntu/.rbenv/bin/rbenv exec bundle exec puma -C /var/www/rails-7-app/shared/config/puma.rb
#ExecStop=/home/ubuntu/.rbenv/bin/rbenv exec bundle exec pumactl -S /var/www/rails-7-app/shared/tmp/pids/puma.state stop
TimeoutSec=15
Restart=always
#added from https://stackoverflow.com/questions/54042621/puma-systemd-script-doesnt-start-puma
PIDFile=/var/www/rails-7-app/shared/tmp/pids/puma.pid
[Install]
WantedBy=multi-user.target
在aws实例/etc/systemd/system/puma.service文件中:
[Unit]
Description=Puma HTTP Server
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/var/www/rails-7-app
#ExecStart=/usr/bin/puma -lc 'bundle exec puma -C /home/ubuntu/rails-7-app/config/puma.rb'
ExecStart=/home/ubuntu/.rbenv/shims/puma -C /var/www/rails-7-app/config/puma.rb
PIDFile=/var/www/rails-7-app/shared/tmp/pids/puma.pid
Restart=always
[Install]
WantedBy=multi-user.target
我尝试跟进几篇 stackoverflow 帖子和其他一些博客,主要编辑了 puma.service 和 puma_appname.service。
如果部署成功,capistrano 日志会在
cap deploy puma:start
之后说类似的内容。
using conf file /home/deploy/myapp/shared/puma.rb
01 ~/.rvm/bin/rvm ruby-2.4.0 do bundle exec puma -C /home/deploy/myapp/shared/puma.rb --daemon
01 Puma starting in single mode...
01
01 * Version 3.9.1 (ruby 2.4.0-p0), codename: Private Caller
01
01 * Min threads: 0, max threads: 8
01
01 * Environment: production
01
01 * Daemonizing...
01