2007年10月22日

在Ubuntu/Debian上面安装Ruby on Rails的生产环境服务器

作者 非鱼

太久没写博客了,闲来无事翻译一篇好文章,相信很多人需要。原文地址:http://ariejan.net/2007/06/20/rails-production-server-setup-and-deployment-on-ubuntudebian/

本文将告诉你如何在Ubuntu/Debian上安装Ruby on Rails的生产环境服务器,以及如何在它上面部署Rails程序。

首先,我们准备安装的东西有:
Ruby 1.8.5
Ruby on Rails 1.2.3
Subversion 1.4
Mysql 5.x Server
Apache 2.2.x
Mongrel Cluster

我假设你已经安装了一个干净的Ubuntu Linux 7.04或者Debian 4.0。如果你还没有,那么你不需要安装DNS或者LAMP等等集成服务器,只需要一个最基本的系统就足够了。

我将会部署一个叫做“myapp”的虚构的Rails应用程序,它使用Mysql数据库,并保存在Subversion中。更多的说明在后面。

我们先把Ruby on Rails服务器跑起来。

更新你的系统

开始之前,先用apt-get把你的系统更新到最新的版本:
$ sudo apt-get update
$ sudo apt-get dist-upgrade

这样做可能会安装一个新的内核,并因此要求你重启。

启用SSH

大部分人会希望使用SSH远程登录他们的服务器,所以我们先安装一个SSH服务器以及客户端:
$ sudo apt-get install openssh-server openssh-client

现在你可以用SSH远程登录了。

以后如果你想使用Capistrano部署你的ROR程序,你会用到SSH。不管怎么说,SSH是个值得安装的好东西。

Subversion

如果你对你的ROR服务器是很认真的,你会需要Subversion。许多部署脚本会从Subversion里面取出你的程序的最新版。这里不需要配置:
$ sudo apt-get install subversion

我们在生产环境服务器上只需要用到它的客户端,因为我们不打算在这里作为Subversion的存储空间。

安装Mysql Server

这是很重要的一步。Ubuntu 7.04和Debian 4.0都已经包含了Mysql 5.0.x的安装包:
$ sudo apt-get install mysql-server mysql-client libmysqlclient15-dev

确保你为Mysql的root用户设置了密码,否则任何用户都能看到你的数据库内容了:
$ mysqladmin -u root -h localhost password ‘secret’
$ mysqladmin -u root -h myhostname password ‘secret’
用你自己的密码代替secret。

试着登录Mysql,确保一切都是正常的:
$ mysql -u root -p
Enter password:
mysql>

好了,Mysql已经就绪了,我们开始安装Ruby on Rails吧。

Ruby,Gems,Rails

安装Ruby非常简单:
$ sudo apt-get install ruby

现在你已经装好了Ruby 1.8.5,你还需要安装其它的东西以便可以用来编译一个本地的Ruby Gems:
$ sudo apt-get install make autoconf gcc ruby1 -dev build-essentials

接下来我会使用常规手段来安装ruby gems,所以我就不使用Ubuntu的包了。
$ wget http://rubyforge.org/frs/download.php/17190/rubygems-0.9.2.tgz
$ tar xvf rubygems-0.9.2.tgz
$ cd rubygems-0.9.2/
$ sudo ruby setup.rb
$ gem -v

现在,来安装Rails及其所依赖的包:
$ sudo gem install rails –include-dependencies
如果你那里出现错误消息说“rails”找不到,加上-remote选项。

嗯,更多的gems包!

接下来,我们要安装一些重要的Ruby Gems包,它们可以让你的生活更简单:
$ sudo gem install mysql capistrano mongrel mongrel-cluster –include-dependencies
其中各个组件的作用是:
mysql – 更好的Mysql连接效率
capistrano – 用到的时候就会知道了
mongrel – Rails的服务器
mongrel-cluster – 使mongrel可以集群化

你会被问许多次来选择各个不同的版本的gems包。记得总是选择最新的那个就行了。(别选win23的,不用解释为什么吧?)

测试Rails和Mysql连接

在继续下面的步骤之前,你也许会希望花点时间测试一下Rails和Mysql。这并不是必须的,不过我推荐这样做,因为这样会为你后面的步骤减少很多问题。

在你自己的目录里创建一个新的Rails应用程序,再创建一个相应的Mysql数据库,编辑config/database.yml加入你正确的root的密码。
$ mysqladmin -u root -p create testapp_development
$ mkdir testapp
$ rails testapp
$ cd testapp
$ vi config/database.yml
$ rake db:migrate

如果你在最后一条命令处出现错误,检查前面的步骤。通常来讲,应该是一切正常的,那么你可以安全的进行下一步了。

大部分人会在他们的config/database.yml里为Mysql配置使用socket连接。注意,不同的发行版中socket的位置是不同的。Ubuntu和Debian的位置在/var/run/mysqld/mysqld.sock。确保你的配置文件指向正确的路径。

Apache 2.2

Ubuntu和Debian的好处就是,他们都包含了Apache 2.2.x。这个版本的Apache包含了支持负载均衡的proxy模块,允许你将负载分派到多个Mongrel服务器上(在你的Mongrel集群中)。我们稍后再做那一步。
$ sudo apt-get install apache2

接下来,我们需要启用一些必须的模块:
$ sudo a2enmod proxy_balancer
$ sudo a2enmod proxy_ftp
$ sudo a2enmod proxy_http
$ sudo a2enmod proxy_connect
$ sudo a2enmod rewrite

Apache就安装好了。我们继续。

准备Rails应用程序

好了,现在我们可以来准备我们的myapp应用程序了。

首先,创建一个生产数据库,并配置在config/database.yml中:
$ mysql -u root -p
> create database myapp_production;
> grant all privileges on myapp_production.* to ‘myapp’@’localhost’ identified by ‘secret_password’

接下来使用gem安装capistrano,你可以按照前面所说的步骤把它安装在你的开发机器上。然后把它应用在你的程序上:
$ sudo gem install capistrano
$ cap –apply-to myapp

看看myapp/config/deploy.rb,这个文件包含了要发布该程序所需的配置信息。下面是myapp程序的示例:
require ‘mongrel_cluster/recipes’
set :application, "myapp"
set :repository, "http://svn.myhost.com/svn/#{application}/trunk"
# We only have one host
role :web, "myapp.com"
role :app, "myapp.com"
role :db,  "myapp.com", :primary => true
# Don’t forget to change this
set :deploy_to, "/home/ariejan/apps/#{application}"
set :mongrel_conf, "#{current_path}/config/mongrel_cluster.yml"

看到了吧,我们已经有几行代码启用了mongrel。

确保该文件的内容符合你的需求。myapp.com是你准备发布该程序的网站的域名。后面我们会创建那个mongrel_cluster.yml文件。

在服务器上,确保你创建了apps目录,现在你可以为部署准备一个基本的文件结构了:
$ cd myapp
$ cap setup

在你的服务器,你会看到/home/ariejan/apps/myapp目录被创建,包括一些子目录。

现在,来配置mongrel。通常,对于一个中等流量网站,你可以把所有的请求交给两个mongrel进程来处理。mongrel服务器只能通过localhost和非默认端口来访问,剩下的问题,交给Apache。

在你的rails程序目录中执行以下命令:
$ mongrel_rails cluster::configure -e production -p 9000 \
-a 127.0.0.1 -N 2 -c /home/ariejan/apps/myapp/current

前面我们看到的那个配置文件已经被创建了,把所有的新文件放入你的subversion里,然后部署你的程序:
$ cap cold_deploy

部署程序会从Subversion里下载所有的最新的代码,并启动mongrel服务器。

部署完成后,生成你的生产数据库并重启mongrel集群。
$ cap migrate
$ cap restart

执行下面的命令来测试你的程序是否运行正常,它应该会返回你的程序的HTML代码:
$ curl -L http://127.0.0.1:9000

配置Apache和负载均衡代理

现在你有两个Mongrel服务器在运行,并且准备好了接受用户请求。但是,你希望你的访问者使用myapp.com,而不是一个IP地址,还带着那个奇怪的端口号。Apache就是用来解决这个问题的。

在/etc/apache2/sites-avalibale目录下创建一个新的文件myapp,添加下面的内容:
<proxy>
  BalancerMember http://127.0.0.1:9000
  BalancerMember http://127.0.0.1:9001
</proxy>
 
<virtualhost>
  ServerName myapp.com
  ServerAlias www.myapp.com
 
  DocumentRoot /home/ariejan/apps/myapp/current/public
 
  <directory>
    Options FollowSymLinks
    AllowOverride None
    Order allow,deny
    Allow from all
  </directory>
 
  RewriteEngine On
 
  RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
  RewriteCond %{SCRIPT_FILENAME} !maintenance.html
  RewriteRule ^.*$ /system/maintenance.html [L]
 
  RewriteRule ^/$ /index.html [QSA]
 
  RewriteRule ^([^.]+)$ $1.html [QSA]
 
  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ balancer://myapps_mongrel_cluster%{REQUEST_URI} [P,QSA,L]
 
  ErrorLog /home/ariejan/apps/myapps/shared/log/tankfactions_errors_log
  CustomLog /home/ariejan/apps/myapps/shared/log/tankfactions_log combined
</virtualhost>

接下来在Apache中启用这个新站点:
$ sudo a2ensite myapp
$ /etc/init.d/apache2 force-reload

某些情况下,你需要对/etc/apache2/mods-enabled/proxy.conf文件做一点小小的改动,把
Order deny,allow
Deny from all
替换成
Order allow,deny
Allow from all
现在你可以通过myapp.com访问你的应用程序了。

维护你的程序

现在,你可以很愉快的开发你的程序并更新(commit到subversion里)。想更新服务器,只需要运行:
$ cap deploy
如果你对数据库做了更改,你可能需要一个long_deploy:
$ cap long_deploy
如果因为某些原因,你的mongrel集群死掉了,只需要重启它:
$ cap restart

That’s it!玩的开心!