如何把Rails7项目部署到ubuntu服务器上

340 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

登录服务器

ssh ubuntu@1.2.3.4 # 替换的你的主机ip
ssh deploy@1.2.3.4

增加deploy用户

adduser deploy
adduser deploy sudo
mkdir /homde/deploy/certs # 后面放ssl证书
exit

Mac客户端使用ssh-copy-id快速登录

brew install ssh-copy-id
ssh-copy-id deploy@1.2.3.4 # 替换的你的主机ip

安装必要的环境依赖

# Adding Node.js repository
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
# Adding Yarn repository
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo add-apt-repository ppa:chris-lea/redis-server
# Refresh our packages list with the new repositories
sudo apt-get update
# Install our dependencies for compiiling Ruby along with Node.js and Yarn
sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev dirmngr gnupg apt-transport-https ca-certificates redis-server redis-tools nodejs yarn

安装Ruby

git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
git clone https://github.com/rbenv/rbenv-vars.git ~/.rbenv/plugins/rbenv-vars
exec $SHELL
rbenv install 2.7.3
rbenv global 2.7.3
ruby -v
# ruby 2.7.3

安装bundler并配置代理

gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/
​
# This installs the latest Bundler, currently 2.x.
gem install bundler
# For older apps that require Bundler 1.x, you can install it as well.
gem install bundler -v 1.17.3
# Test and make sure bundler is installed correctly, you should see a version number.
bundle -v
# Bundler version 2.0
bundle config mirror.https://rubygems.org https://gems.ruby-china.com
# 如果bundle not found
rbenv rehash

Installing NGINX & Passenger

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger focal main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update
sudo apt-get install -y nginx-extras libnginx-mod-http-passenger
if [ ! -f /etc/nginx/modules-enabled/50-mod-http-passenger.conf ]; then sudo ln -s /usr/share/nginx/modules-available/mod-http-passenger.load /etc/nginx/modules-enabled/50-mod-http-passenger.conf ; fi
sudo ls /etc/nginx/conf.d/mod-http-passenger.conf

change the passenger_ruby

sudo vim /etc/nginx/conf.d/mod-http-passenger.conf
passenger_ruby /home/deploy/.rbenv/shims/ruby;

启动Nginx

sudo service nginx start

配置Nginx(后面所有步骤的myapp请根据情况更改)

sudo rm /etc/nginx/sites-enabled/default
sudo vim /etc/nginx/sites-enabled/myapp
server {
  listen 80;
  listen [::]:80;

  server_name www.rubyc.cn;
  root /home/deploy/myapp/current/public;

  passenger_enabled on;
  passenger_app_env production;

  location /cable {
    passenger_app_group_name myapp_websocket;
    passenger_force_max_concurrent_requests_per_process 0;
  }

  # Allow uploads up to 100MB in size
  client_max_body_size 100m;

  location ~ ^/(assets|packs) {
    expires max;
    gzip_static on;
  }
}

重启Nginx

sudo service nginx reload
sudo service nginx start

查看Nginx是否启动

passenger-status # 如无报错则说明正常运行

安装PostgreSQL Database

sudo apt-get install postgresql postgresql-contrib libpq-dev
sudo su - postgres
createuser --pwprompt deploy
# Qq759337828pgsql..
createdb -O deploy myapp
exit


You can manually connect to your database anytime by running psql -U deploy -W -h 127.0.0.1 -d myapp. Make sure to use 127.0.0.1 when connecting to the database instead of localhost.

安装 MySQL Database(把下面的password替换成你想设置的密码,后面步骤要用到)

sudo apt-get install mysql-server mysql-client libmysqlclient-dev
sudo mysql_secure_installation
# Open the MySQL CLI to create the user and database
mysql -u root -p



CREATE DATABASE IF NOT EXISTS myapp;
CREATE USER IF NOT EXISTS 'deploy'@'localhost' IDENTIFIED BY 'password';
CREATE USER IF NOT EXISTS 'deploy'@'%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON myapp.* TO 'deploy'@'localhost';
GRANT ALL PRIVILEGES ON myapp.* TO 'deploy'@'%';
FLUSH PRIVILEGES;
\q

如果你的项目使用mysql或pg,请确保你的Gemfile文件中有相关gem(根据需要添加或者删除)

gem "pg", "~> 1.1"
gem "mysql2"

配置database连接信息,以MySQL为例(如果是pg应该不需要修改代码,因为默认生成的是pg配置信息)

# config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
    socket: /tmp/mysql.sock

把本地项目推到你的代码管理仓库(已推送请忽略)

把服务器的id_rsa.pub添加到你代码仓库的delopy key中

# 服务器运行
ssh-keygen -t rsa # 一直按Enter键即可
cat ~/.ssh/id_rsa.pub # 把这个打印出的秘文添加到代码仓库的delopy key中

本地项目安装Setting Up Capistrano

gem 'capistrano', '~> 3.11'
gem 'capistrano-rails', '~> 1.4'
gem 'capistrano-passenger', '~> 0.2.0'
gem 'capistrano-rbenv', '~> 2.1', '>= 2.1.4'

bundle
cap install STAGES=production


# Capfile
require 'capistrano/rails'
require 'capistrano/passenger'
require 'capistrano/rbenv'

set :rbenv_type, :user
set :rbenv_ruby, '3.1.1'

# config/deploy.rb
# config valid for current version and patch releases of Capistrano
lock "~> 3.17.0"

set :application, "myapp"
set :repo_url, "your_repo_url"

# 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, "/home/deploy/#{fetch :application}"

# 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",'vendor/bundle', "tmp/webpacker",'.bundle', "public/system", "vendor", "storage", 'public/uploads'

# 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

================================================

服务器主机配置相关参数(请将👇的相关信息按照你主机的信息填写)

sudo vim /home/deploy/myapp/.rbenv-vars
# For Postgres
DATABASE_URL=postgresql://deploy:PASSWORD@127.0.0.1/myapp

# For MySQL
DATABASE_URL=mysql2://deploy:Password@localhost/myapp

RAILS_MASTER_KEY=xxx(下个步骤生成)
SECRET_KEY_BASE=yyyy(下个步骤生成)

# etc...

项目生成master.key

EDITOR="vim" rails credentials:edit
secret_key_base:                     de99780361eb9ddc18262d723a18ba038ad44703fca4b34936b16a90ef8c7a53cb9d04d41e9788fc9d5431b1e1a45a754ec448c46ab7e9d55f0c15e15a32d2f6
# 把这的秘钥替换到yyyy

# 查看master.key
cat master.key
# 把结果替换上面的xxx

项目启用master.key

# config/environments/production.rb
 config.require_master_key = true

检查cap

cap production deploy:check # 如有报错请根据提示修改

部署

cap production deploy # 如有报错请根据提示修改

大功告成

配置SSL(HTTPS)

先把你的ssl证书上传到服务器的/home/deploy/目录下

sudo vim /etc/nginx/sites-enabled/myapp

server {
    listen 443 ssl;

    server_name your_domain;
    ssl_certificate your_domain.crt;
    ssl_certificate_key your_domain.key;

    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    root /home/deploy/myapp/current/public;
    passenger_enabled on;
    passenger_app_env production;

    location /cable {
      passenger_app_group_name myapp_websocket;
      passenger_force_max_concurrent_requests_per_process 0;
    }

    # Allow uploads up to 100MB in size
    client_max_body_size 100m;
    location ~ ^/(assets|packs) {
      expires max;
      gzip_static on;
    }
}
server {
    listen 80;
    #填写绑定证书的域名
    server_name your_domain; 
    #把http的域名请求转成https
    return 301 https://$host$request_uri; 
}

可能遇到的问题(修改项目文件后及时提交到git)

  1. Error: The application encountered the following error: You have already activated strscan 1.0.3, but your Gemfile requires strscan 3.0.1. Since strscan is a default gem, you can either remove your dependency on it or try updating to a newer version of bundler that supports strscan as a default gem. (Gem::LoadError)

    解决办法:

    # Gemfile.lock 找到strscan的3.0.1改成1.0.3,改完要及时提交到git
    strscan (3.0.1)改成下面的
    strscan (1.0.3)
    
  2. 访问项目时报错

    sudo cat /var/log/nginx/error.log # 看一下报错原因,根据报错原因修改
    
  3. Error: The application encountered the following error

    可能的原因

    3.1 你没启动nginx

    sudo service nginx start
    

\