Record a Rails project deployment
Cloud server
Tencent cloud and Ubuntu Server 16.04.1 LTS 64-bit
Project example
Using a blog demo, Getting Started with Rails from the documentation on the Rails website
Installing the Server Software
Use Ubuntu’s built-in suite management tool apt-get
-
Update the software list
sudo apt-get update Copy the code
-
Install the required software for Ruby on Rails
sudo apt-get install -y build-essential git-core bison openssl libreadline6-dev curl zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 autoconf libc6-dev libpcre3-dev libcurl4-nss-dev libxml2-dev libxslt-dev imagemagick nodejs libffi-devCopy the code
-
Install Ruby and use Brighbox’s compiled Ruby
sudo apt-get install software-properties-common sudo apt-add-repository ppa:brightbox/ruby-ng sudo apt-get update sudo Apt to get the install ruby2.6 ruby2.6 - devCopy the code
-
Replace the gem source and install the Bundler gem
gem source gem source -r https://rubygems.org/ gem source -a https://gems.ruby-china.com sudo gem install bundler Copy the code
-
Install Rails
Gem install Rails -v 5.1.7Copy the code
-
Install the database using PostgreSQL or MySQL
Sudo apt-get install postgresql libpq-dev postgresql-contrib # Modify the password of account postgres sudo -u postgres PSQL Sudo -u postgres createdb blog postgres=#\password # remember the password in database.ymlCopy the code
-
Install Nginx + Passenger Web server from Installing Passenger + Nginx
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7 sudo apt-get install -y apt-transport-https ca-certificates sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger xenial main > /etc/apt/sources.list.d/passenger.list' sudo apt-get update sudo apt-get install -y nginx-extras passenger Copy the code
-
Welcome to Nginx on Ubuntu!
Creating a Deployment User
- Adding a Deploy user
Sudo adduser --disabled-password deploy sudo su deploy mkdir ~/. SSH touch ~/. SSH /authorized_keys # Cat ~/.ssh/id_rsa.pub # Paste the public key vi ~/. SSH /authorized_keys chmod 700 ~/. SSH chmod 644 ~/. SSH /authorized_keys # After you exit, the local PC can use SSH to deploy@< host IP address location > to log in without passwordCopy the code
Automated deployment
-
To install the Capistrano deployment tool, use the blog project
Modify the blog project Gemfile with #!! , bundle install after modification
source 'https://gems.ruby-china.com/' git_source(:github) do |repo_name| repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") "https://github.com/#{repo_name}.git" end # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.1.7' # Use sqlite3 as the database for Active Record # Use Puma as the app server gem 'Puma ', '~> 3.7' # Use SCSS for stylesheets gem 'sass-rails', # Use Uglifier as compressor for JavaScript assets gem 'Uglifier ', # '> = 1.3.0 See https://github.com/rails/execjs#readme for more supported runtimes # gem' therubyracer, platforms: :ruby # Use CoffeeScript for .coffee assets and views gem 'coffee-rails', '~> 4.2' # Turbolinks makes navigating your Web Application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production # gem 'Redis' '~> 4.0' # Use ActiveModel has_secure_password # Use Capistrano for deployment # gem 'Capistrano -rails', group: :development #!! group :production do gem 'pg' end #!!! group :development, :test do gem 'sqlite3' # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] # Adds support for Capybara system testing and selenium driver gem 'capybara', '>= 2.15' gem 'selenium-webdriver' gem 'rspec-rails' #!! gem 'capistrano-rails' gem 'capistrano-passenger' end group :development do # Access an IRB console on exception pages Or by using <%= console %> anywhere in the code. gem 'web-console', '>= 3.3.0' gem 'listen', '>= 3.0.5', '< 3.2' # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring' gem 'spring-watcher-listen', '~> FFFFFF 'end # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', FFFFFF: [:mingw, :mswin, :x64_mingw, :jruby]Copy the code
-
Capistrano is configured locally and executed in the project directory
cap install Copy the code
Edit Capfile file with #!!
# 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 #!!! require 'capistrano/rails' require 'capistrano/passenger' # 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" # Load custom tasks from `lib/capistrano/tasks` if you have any defined Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }Copy the code
-
Change config/deploy.rb to #!!
# config valid for current version and patch releases of Capistrano #!!! Sh "ssh-add" lock "~> 3.16.0" #! set :application, "blog" #!!! Send your project to the remote Github repository, Set: repo_URL, "[email protected]: XXX /blog.git" # 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" #!!! set :deploy_to, "/home/deploy/blog" # 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" #!!! append :linked_files, "config/database.yml", "config/secrets.yml" # Default value for linked_dirs is [] # append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system" #!!! append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system" #!!! set :passenger_restart_with_touch, true # 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 #!!! set :keep_releases, 5 # Uncomment the following to require manually verifying the host key before first deploy. # set :ssh_options, verify_host_key: :secureCopy the code
-
Modify the config/deploy/production. Rb, attention tag #!!!!!!
#!!!!!! set :branch, "master" # server-based syntax # ====================== # Defines a single server with a list of roles and multiple properties. # You can define all roles on a single server, or split them: # server "example.com", user: "deploy", roles: %w{app db web}, my_property: :my_value # server "example.com", user: "deploy", roles: %w{app web}, other_property: :other_value # server "db.example.com", user: "deploy", roles: %w{db} #!!! Server "15x.13x.12x.18", user: "deploy", roles: %w{app db web}, my_property: :my_value # role-based syntax # ================== # Defines a role with one or multiple servers. The primary server in each # group is considered to be the first unless any hosts have the primary # property set. Specify the username and a domain or IP for the server. # Don't use `:all`, it's a meta role. # role :app, %w{[email protected]}, my_property: :my_value # role :web, %w{[email protected] [email protected]}, other_property: :other_value # role :db, %w{[email protected]} # Configuration # ============= # You can set any configuration variable like in config/deploy.rb # These variables are then only loaded and set in this stage. # For available Capistrano configuration variables see the documentation page. # http://capistranorb.com/documentation/getting-started/configuration/ # Feel free to add new variables to customise your setup. # Custom SSH Options # ================== # You may pass any option but keep in mind that net/ssh understands a # limited set of options, consult the Net::SSH documentation. # http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start # # Global options # -------------- # set :ssh_options, { # keys: %w(/home/user_name/.ssh/id_rsa), # forward_agent: false, # auth_methods: %w(password) # } # # The server-based syntax can be used to override options: # ------------------------------------ # server "example.com", # user: "user_name", # roles: %w{web app}, # ssh_options: { # user: "user_name", # overrides user setting above # keys: %w(/home/user_name/.ssh/id_rsa), # forward_agent: false, # auth_methods: %w(publickey password) # # password: "please use keys" # }Copy the code
-
Execute cap Production deploy: Check in the local project directory, which automatically creates some Capistrano directories and files on the automatic login remote server
Cap Production deploy:check # will have a missing database.yml file Error, continue to see the next stepCopy the code
-
The server is set to database.yml and secrets.yml
# login or switch to deploy users, add/home/deploy/blog/Shared/config/database. Yml production: adapter: postgresql pool: 25 database: blog host: localhost username: postgres password: XXXXXX # execute rake secret under local project Generate random number for later use efab0aae7352a424fae818574934baf1107f96785dbdf6ee5f8e7054399a4bbbb561dfc1183e1f20f2c247d9cd437fa0908d2fcb7517b0d7c34e61b4 59 d5969d # login or switch to deploy users, add/home/deploy/blog/Shared/config/secrets. Yml production: secret_key_base: Paste in the random number we just created, there is a space here, or parse # # # # # # # # #Copy the code
-
Execute Cap Production deploy in the native blog directory for deployment
Perform logging into remote servers, pulling code from GitHub repositories, installing gems, migrating databases, compiling assets, and more
ssh-add Identity added: /Users/gekang/.ssh/id_rsa (/Users/gekang/.ssh/id_rsa) 00:00 git:wrapper 01 mkdir -p /tmp ✔ 01 [email protected] 0.351s Uploading /tmp/git-ssh-0633e09da1de2a9e42f4.sh 100.0% 02 chmod 700 /tmp/git-ssh-0633e09da1de2a9e42f4.sh ✔ 02 [email protected] 0.077s 00:00 git:check 01 git ls-remote [email protected]:grackanil/blog.git HEAD 01 ac469184b28aec29e409430ab7bdc0eb6af76e5b HEAD ✔ 01 [email protected] 6.136s 00:06 deploy:check:directories 01 mkdir -p /home/deploy/blog/shared /home/deploy/blog/releases ✔ 01 [email protected] 0.035s 00:06 deploy:check:linked_dirs 01 mkdir -p /home/deploy/blog/shared/log /home/deploy/blog/shared/tmp/pids /home/… ✔ 01 [email protected] 0.464s 00:07 deploy:check:make_linked_dirs 01 mkdir -p /home/deploy/blog/shared/config ✔ 01 [email protected] 0.031s 00:08 git:clone The repository mirror is at /home/deploy/blog/repo 00:08 git:update 01 git remote set-url origin [email protected]:grackanil/blog.git ✔ 01 [email protected] 0.077s 02 git remote update --prune 02 Fetching origin ✔ 02 [email protected] 5.568s 00:14 git:create_release 01 mkdir -p /home/deploy/blog/releases/20210622112320 ✔ 01 [email protected] 0.075s 02 git archive master | /usr/bin/env tar -x -f - -C /home/deploy/blog/releases/20… ✔ 02 [email protected] 0.092s 00:14 deploy:set_current_revision 01 echo "ac469184b28aec29e409430ab7bdc0eb6af76e5b" > REVISION ✔ 01 [email protected] 0.079s 00:14 deploy:symlink:linked_files 01 mkdir -p /home/deploy/blog/releases/20210622112320/config ✔ 01 [email protected] 0.070s 02 rm /home/deploy/blog/releases/20210622112320/config/database.yml ✔ 02 [email protected] 0.074s 03 ln -s /home/deploy/blog/shared/config/database.yml /home/deploy/blog/releases/… ✔ 03 [email protected] 0.071s 04 rm /home/deploy/blog/releases/20210622112320/config/secrets.yml ✔ 04 [email protected] 0.071s 05 ln -s /home/deploy/blog/shared/config/secrets.yml /home/deploy/blog/releases/2… ✔ 05 [email protected] 0.071s 00:15 deploy:symlink:linked_dirs 01 mkdir -p /home/deploy/blog/releases/20210622112320 /home/deploy/blog/releases/… ✔ 01 [email protected] 0.070s 02 rm -rf /home/deploy/blog/releases/20210622112320/log ✔ 02 [email protected] 0.070s 03 ln -s /home/deploy/blog/shared/log /home/deploy/blog/releases/20210622112320/l… ✔ 03 [email protected] 0.073s 04 ln -s /home/deploy/blog/shared/tmp/pids /home/deploy/blog/releases/20210622112… ✔ 04 [email protected] 0.071s 05 ln -s /home/deploy/blog/shared/tmp/cache /home/deploy/blog/releases/2021062211… ✔ 05 [email protected] 0.078s 06 ln -s /home/deploy/blog/shared/tmp/sockets /home/deploy/blog/releases/20210622… ✔ 06 [email protected] 0.077s 07 ln -s /home/deploy/blog/shared/public/system /home/deploy/blog/releases/202106… ✔ 07 [email protected] 0.069s 08 rm -rf /home/deploy/blog/releases/20210622112320/public/assets ✔ 08 [email protected] 0.078s 09 ln -s /home/deploy/blog/shared/public/assets /home/deploy/blog/releases/202106… ✔ 09 [email protected] 0.072s 00:16 bundler:config 01 bundle config --local deployment true 01 You are replacing the current local value of deployment, which is currently nil ✔ 01 [email protected] 0.241s 02 bundle config --local path /home/deploy/blog/shared/bundle 02 You are replacing the current local value of path, which is currently nil ✔ 02 [email protected] 0.317s 03 bundle config --local without development:test 03 You are replacing the current local value of without, which is currently nil ✔ 03 [email protected] 0.308s 00:18 bundler:install The Gemfile's dependencies are satisfied, skipping installation 00:18 deploy:assets:precompile 01 bundle exec rake assets:precompile 01 Yarn executable was not detected in the system. 01 Download Yarn at https://yarnpkg.com/en/docs/install ✔ 01 [email protected] 1.870s 00:20 deploy:assets:backup_manifest 01 mkdir -p /home/deploy/blog/releases/20210622112320/assets_manifest_backup ✔ 01 [email protected] 0.073s 02 cp /home/deploy/blog/releases/20210622112320/public/assets/.sprockets-manifest… ✔ 02 [email protected] 0.071s 00:20 deploy:migrate [deploy:migrate] Run `rake db:migrate` 00:20 deploy:migrating 01 bundle exec rake db:migrate ✔ 01 [email protected] 1.584s 00:21 deploy:symlink:release 01 ln -s /home/deploy/blog/releases/20210622112320 /home/deploy/blog/releases/cur… ✔ 01 [email protected] 0.075s 02 mv /home/deploy/blog/releases/current /home/deploy/blog ✔ 02 [email protected] 0.072s 00:22 passenger:restart 01 mkdir -p /home/deploy/blog/releases/20210622112320/tmp ✔ 01 [email protected] 0.072s 02 touch /home/deploy/blog/releases/20210622112320/tmp/restart.txt ✔ 02 [email protected] 0.072s 00:22 deploy:cleanup Keeping 5 of 6 deployed releases on 15x.x3x.xxx.13 01 rm -rf /home/deploy/blog/releases/20210622073535 ✔ 01 [email protected] 0.080s 00:22 deploy:log_revision 01 echo "Branch master (at ac469184b28aec29e409430ab7bdc0eb6af76e5b) deployed as … ✔ 01 [email protected] 0.073s Copy the code
Then you just need to change the code and deploy
git commit cap production deploy Copy the code
Note that the current directory is generated here and will be needed later
Set the Nginx
With root permission, set /etc/nginx/nginx.conf to #!!
#!!!!!! env PATH; user www-data; worker_processes auto; pid /run/nginx.pid; events { worker_connections 768; # multi_accept on; } http { #!!! passenger_show_version_in_header off; #!!!!!! server_tokens off; #!!!!!! client_max_body_size 100m; gzip on; gzip_disable "msie6"; #!!!!!! gzip_comp_level 5; gzip_min_length 256; gzip_proxied any; gzip_vary on; gzip_types application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/xml text/plain text/javascript text/x-component; #!!!!!! include /etc/nginx/passenger.conf; # down slightlyCopy the code
Set /etc/nginx/sites-enabled/blog.conf as root
server { listen 80; server_name 15x.x3x.xxx.13; # with your own server IP address root/home/deploy/blog/current/public; # current, passenger_enabled on; passenger_min_instances 1; location ~ ^/assets/ { expires 1y; add_header Cache-Control public; add_header ETag ""; break; }}Copy the code
Restart the Nginx
sudo service nginx restart Copy the code
Open IP address, done, happy
Reference documentation
- Ruby China:ruby-china.org/wiki
- Getting Started with Rails:guides.rubyonrails.org/getting_sta…
- Brighbox:www.brightbox.com/docs/ruby/u…
- Capistrano:capistranorb.com/
- Ruby on Rails:guides.rubyonrails.org/
- Rails: ihower. Tw/Rails/Fulls…
- Installing Passenger + Nginx www.phusionpassenger.com/library/ins…
- Gorails:gorails.com/deploy/ubun…