💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 7.5 专业部署方案 现在注册页面可以使用了,该把应用部署到生产环境了。虽然我们从[第 3 章](chapter3.html#mostly-static-pages)就开始部署了,但现在应用才真正有点用,所以借此机会我们要把部署过程变得更专业一些。具体而言,我们要在生产环境的应用中添加一个重要功能,保障注册过程的安全性,还要把默认的 Web 服务器换成一个更适合在真实环境中使用的服务器。 为了部署,现在你应该把改动合并到 `master` 分支中: ``` $ git add -A $ git commit -m "Finish user signup" $ git checkout master $ git merge sign-up ``` ## 7.5.1 在生产环境中使用 SSL 在本章开发的注册表单中提交数据注册用户时,用户的名字、电子邮件地址和密码会在网络中传输,因此可能在途中被拦截。这是应用的重大潜在安全隐患,解决的方法是使用“安全套接层”(Secure Sockets Layer,简称 SSL),[[12](#fn-12)]在数据离开浏览器之前加密相关信息。我们可以只在注册页面启用 SSL,不过整站启用也容易实现。整站都启用 SSL 后,[第 8 章](chapter8.html#log-in-log-out)实现的用户登录功能也能从中受益,而且还能防范 [8.4 节](chapter8.html#remember-me)讨论的会话劫持。 启用 SSL 很简单,只要在生产环境的配置文件 `production.rb` 中去掉一行代码的注释即可。如[代码清单 7.27](#listing-ssl-in-production) 所示,我们只需设置 `config` 变量,强制在生产环境中使用 SSL。 ##### 代码清单 7.27:配置应用,在生产环境中使用 SSL config/environments/production.rb ``` Rails.application.configure do . . . # Force all access to the app over SSL, use Strict-Transport-Security, # and use secure cookies. config.force_ssl = true . . . end ``` 然后,我们要在远程服务器中设置 SSL。这个过程包括为自己的域名购买和设置 SSL 证书,有很多工作要做。不过幸运的是,我们并不需要处理这些事,因为在 Heroku 中运行的应用(例如我们的演示应用),可以直接使用 Heroku 的 SSL 证书。所以,[7.5.2 节](#production-webserver)部署应用后,会自动启用 SSL。(如果你想在自己的域名上使用 SSL,例如 `www.example.com`,参照 [Heroku 对 SSL 的说明](http://devcenter.heroku.com/articles/ssl)。) ## 7.5.2 生产环境中的 Web 服务器 启用 SSL 后,我们要配置应用,让它使用一个适合在生产环境中使用的 Web 服务器。默认情况下,Heroku 使用纯 Ruby 实现的 WEBrick,这个服务器易于搭建,但不能很好地处理巨大流量。因此,[WEBrick 不适合在生产环境中使用](https://devcenter.heroku.com/articles/ruby-default-web-server),我们要[换用能处理大量请求的 Puma](https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server)。 我们按照 [Heroku 文档中的说明](https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server),换用 Puma。第一步,在 `Gemfile` 中添加 `puma` gem,如[代码清单 7.28](#listing-puma-gemfile) 所示。因为在本地不需要使用 Puma,所以我们把 `puma` 放在 `:production` 组中。 ##### 代码清单 7.28:在 `Gemfile` 中添加 Puma ``` source 'https://rubygems.org' . . . group :production do gem 'pg', '0.17.1' gem 'rails_12factor', '0.0.2' gem 'puma', '2.11.1' end ``` 因为我们配置过 Bundler,不让它安装生产环境的 gem([3.1 节](chapter3.html#sample-app-setup)),所以[代码清单 7.28](#listing-puma-gemfile) 不会在开发环境中安装额外的 gem,不过我们还是要运行 Bundler,更新 `Gemfile.lock`: ``` $ bundle install ``` 下一步是创建文件 `config/puma.rb`,然后写入[代码清单 7.29](#listing-production-webserver-config) 中的内容。这段代码直接摘自 [Heroku 的文档](https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server),[[13](#fn-13)]没必要理解它的意思。 ##### 代码清单 7.29:生产环境所用 Web 服务器的配置文件 config/puma.rb ``` workers Integer(ENV['WEB_CONCURRENCY'] || 2) threads_count = Integer(ENV['MAX_THREADS'] || 5) threads threads_count, threads_count preload_app! rackup DefaultRackup port ENV['PORT'] || 3000 environment ENV['RACK_ENV'] || 'development' on_worker_boot do # Rails 4.1+ 专用的职程设置 # 详情参见:https://devcenter.heroku.com/articles/ # deploying-rails-applications-with-the-puma-web-server#on-worker-boot ActiveRecord::Base.establish_connection end ``` 最后,我们要新建一个 `Procfile` 文件,告诉 Heroku 在生产环境运行一个 Puma 进程。这个文件的内容如[代码清单 7.30](#listing-procfile) 所示。`Procfile` 文件和 `Gemfile` 文件一样,应该放在应用的根目录中。 ##### 代码清单 7.30:创建 Puma 需要的 `Procfile` 文件 ./Procfile ``` web: bundle exec puma -C config/puma.rb ``` 生产环境的 Web 服务器配置好之后,我们可以提交并部署了:[[14](#fn-14)] ``` $ bundle exec rake test $ git add -A $ git commit -m "Use SSL and the Puma webserver in production" $ git push $ git push heroku $ heroku run rake db:migrate ``` 现在,注册页面可以在生产环境中使用了,注册成功后显示的页面如[图 7.24](#fig-signup-in-production)。注意图中的地址栏,使用的是 `https://`,而且还有一个锁状图标——表明启用了 SSL。 ![signup in production 3rd edition](https://box.kancloud.cn/2016-05-11_5733304c83abb.png)图 7.24:在生产环境中注册 ## 7.5.3 Ruby 的版本 部署到 Heroku 时,可能会看到类似下面的提醒消息: ``` ###### WARNING: You have not declared a Ruby version in your Gemfile. To set your Ruby version add this line to your Gemfile: ruby '2.1.5' ``` 经验表明,对本书面向的读者来说,明确指定 Ruby 的版本号要做很多额外工作,得不偿失,[[15](#fn-15)]所以现在你应该忽略这个提醒。为了让演示应用和系统中的 Ruby 版本保持最新,会遇到很多问题,而且不同的版本之间没有太大的差异。不过要记住,如果想在 Heroku 中运行重要的应用,建议在 `Gemfile` 中明确指定 Ruby 版本号,尽量减少开发环境和生产环境之间的差异。