posts - 262,  comments - 221,  trackbacks - 0
【1. 下载Virtual Box】
==================================================
在/etc/apt/sources.list文件的末尾添加一行
  deb http://download.virtualbox.org/virtualbox/debian lucid contrib non-free

添加Oracle的key文件
  wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add -

以root用户身份执行
  sudo apt-get update
  sudo apt-get install virtualbox-4.0  
==================================================


【2. 安装vagrant和Linux虚拟机】
==================================================
  gem install vagrant
  vagrant box add base http://files.vagrantup.com/lucid32.box

如果出现gem无法安装的情况(例如链接被重置,请使用VPN连接后再安装gem)
==================================================


【3. 配置Ubuntu】
==================================================
  mkdir ubuntu  # 控制虚拟机配置的目录
  cd ubuntu
  vagrant init     # 初始化vagrant的环境
  vagrant up     # 创建vagrant的运行环境
  vagrant ssh    # 以SSH方式连接登录

当使用vagrant ssh方式登录的时候,会以一个名为vagrant的用户身份登录到虚拟机
(lucid32),这个用户具备有管理权限(虚拟机预设用户)。如果使用的虚拟机不是vagrant
网站提供的,那么默认没有vagrant用户,需要在虚拟机端创建一个具备管理权限的用户

  useradd -d /home/user -m -s /bin/bash -G admin user
  passwd user
  su user

其中第一个命令的创建一个名为user的用户,默认的home目录位于/home/user,默认
的shell使用/bin/bash,该用户的组为admin(-G) 。然后为该用户创建新的密码并切换到
该用户(我们可以使用vagrant作为用户名),以后所有的操作都在该用户下进行(不再使用
vagrant,直接操纵虚拟机)
==================================================


【4. 升级虚拟机的aptitude package】
==================================================
在连接到虚拟机的情况下,执行:

  sudo aptitude update
  sudo aptitude -y install build-essential git-core curl

确保该repository下的所有最新source会被下载并缓存到本地,并安装几个必需的包,
其中build-essential包含了若干编译源代码的必要工具,git-core包含了GIT的核心功能,
我们将用来提交代码,curl允许我们访问某个指定的URL并download该URL的内容
==================================================


【5. 安装RVM】
==================================================
通过RVM官网提供的脚本来安装RVM,并默认安装为系统级别(即sudo打头的)
 
  sudo bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )
 
如果在这个过程有出现关于“认证”  的错误,请为curl添加一个"-k"开关参数

  sudo bash < <(curl -sk https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)

使用Multi-user mode(System mode)安装的,默认将RVM安装在/usr/local/rvm下。

再次安装部分Ruby的依赖包

  sudo aptitude -y install build-essential bison openssl \
          libreadline6 libreadline6-dev curl git-core zlib1g \
          zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 \
          libsqlite3-dev sqlite3 libxml2-dev libxslt-dev \
          autoconf libc6-dev libpq-dev libcurl4-openssl-dev          

The installation process is similar for both installation methods, however, when
installing a multi-user configuration, do not run the installer directly as root.
Always use the sudo command         
==================================================


【6. 配置RVM的加载】
==================================================
The rvm function will be automatically configured for every user on the system
if you install as root. This is accomplished by loading /etc/profile.d/rvm.sh on login.

Most Linux distributions default to parsing /etc/profile which contains the logic to
load all files residing in the /etc/profile.d/ directory.

Once you have added the users you want to be able to use RVM to the rvm group,
those users MUST log out and back in to gain rvm group membership because
group memberships are only evaluated by the operating system at initial login time.

Also, you only use the sudo command during the install process. In Multi-User
configurations, any operations which require sudo access must use the rvmsudo
command which preserves the RVM environment and passes this on to sudo.

There are very few cases where rvmsudo is required once the core install is
completed, except for when updating RVM itself. There is never a reason to use
sudo post-install.

如果是在非vagrant的虚拟机上,我们需要手动为连接的用户添加一个所属组:rvm

  sudo usermod -a -G rvm user
  sudo echo 'source "/usr/local/rvm/scripts/rvm"' >> /etc/profile
  exit
 
注意上面的命令在执行后,当前用户必须注销后重新登录以使更改起效。

通过如下命令来检测一切是否正常:

  type rvm | head -1
  rvm is a function

在完成RVM的配置后,可以看一下还有需要安装的,运行如下的命令检查:

  rvm requirements
==================================================

 
【7. 安装Ruby及其包管理器】
==================================================
  rvm install 1.9.2
  rvm use --default 1.9.2
  gem install bundler rake
==================================================


【8. 为发布应用创建一个专用的用户】
==================================================
为每一个应用的发布创建一个对应的用户,可以方便我在发布多个应用的时候区分当前
到底是处在那个应用。

其次对于目录,数据库的所有权都属于创建者,所以为应用创建特定的用户有利于我们隔
离目录和DB的访问权限。

  sudo useradd ticketeeapp.com -s /bin/bash -m -d /home/ticketeeapp.com
  sudo chown -R ticketeeapp.com /home/ticketeeapp.com
  sudo passwd ticketeeapp.com
==================================================


【9. 使用SSH连接】
==================================================
SSH连接是基于key authorized的验证机制,它由634位的随机字符和数字组成密码。

这里我需要为连接到虚拟机的用户、发布应用的用户都采用SSH认证方式。

注意:前面我使用vagrant ssh的时候,不需要密码就可以连接到虚拟机。就是因为在
vagrant的虚拟机中,已经有默认的key认证文件了,所以不需要再重新生成key文件,
否则会导致vagrant ssh无法登录。

但是如果不是使用vagrant的虚拟机,则需要手工创建key文件了。key文件分为public
key和private key两种。public key存储在服务器端而private key存储在服务器/客户端。
当使用SSH连接时,服务器会验证public key和private key是否匹配(两者的private key
是否相同)

  # 登录服务器后,在当前用户的home目录下创建.ssh目录
  mkdir ~/.ssh
  # 在 "本地机器" 将当前public key拷贝到服务器的.ssh目录下,以登录用户名重命名
  # 这个过程需要输入登录的密码
  scp ~/.ssh/id_rsa.pub user@your-server:~/.ssh/[your_name]_key.pub
  # 生成private key
  cat ~/.ssh/[your_name]_key.pub >> ~/.ssh/authorized_keys
  # 修改private key的读写权限为仅当前用户可读写
  chmod 600 ~/.ssh/authorized_keys
 
上面的user@your-server中,user是当前登录服务器的用户名,your-server在这里是
服务器的名称。如果是使用vagrant,那么这里的user就是vagrant,而your-server则
是localhost。

当配置完成后,断开和服务器的连接,再重新使用SSH方式登录,这个时候应该不需要
再次输入密码就可以连接。表明SSH配置起作用了。
 
接下来切换用户到App发布用户

  sudo  su ticketeeapp.com
 
然后重新跑一遍上面的命令。注意在scp命令时把user换成App发布用户的名称
==================================================


【10. 取消密码验证】
==================================================
切换回原来登录的用户账户,并打开如下的文件

  sudo nano /etc/ssh/sshd_config
 
修改其中的配置选择如下:

  PasswordAuthentication  no  
  PermitRootLogin no

退出nano编辑器,然后在命令行下执行如下命令,重启SSH服务:

  service ssh restart
 
至此完成了所有的基于key authentication的用户验证  
==================================================


【11. 安装数据库】
==================================================
在Console下执行:

  sudo apt-get install mysql-server
  sudo apt-get install sqlite3 libsqlite3-dev
  gem install sqlite3-ruby

在安装的过程中会被要求输入root用户的密码,安装成功后将会自动加入到开机自启动
==================================================


【12. 为发布代码到GitHub的Repository创建密钥】
==================================================
首先为发布代码到GitHub创建一个密钥,这个过程会产生一个公钥和一个密钥。密钥必
须妥善保存,而公钥可以作为GitHub上我们发布代码的key authentication

首先切换到App应用发布的用户,在终端下执行命令:

  ssh-keygen -t rsa        #产生密钥
  cat ~/.ssh/id_rsa.pub  #查看公钥的内容,拷贝粘帖到GitHub对应管理页面的输入框

注意这些key是可以和Web应用关联在一起的,所以这个private key是针对单个App的。
当完成这些操作后,可以运行下面的命令验证key认证是否成功:

  git clone git@github.com:our_username/ticketee.git ~/ticketee
 
这个命令会从GitHub的ticketee应用下,拷贝内容到当前用户目录下,名称叫ticketee。  
如果有这个目录存在且包含所有应该包含的内容,证明配置成功。此时我们可以删除这个
目录。  
==================================================  
 

 【13. 配置Capistrano】
==================================================
首先是把Capistrano 这个gem添加到应用中,再重新执行一次 bundle install

  group :development do
    gem 'capistrano'
  end
 
然后在应用的根目录执行命令:capify .

在应用根目录下生成两个文件:capfile 和 config/deploy.rb。其中capfile中调用了config/
deploy.rb文件,用来读取所有和部署相关的信息。在config/deploy.rb文件中,有若干项是
需要配置的

  set :application, "set your application name here"
  set :repository,  "set your repository location here"  # 注意这里是GitHub的repository路径
  set :scm, :git
  set :port, 2200
  set :user, "set your user name here as the app user" # 由于使用了密钥不需要密码
  set :deploy_to, "PATH_TO_USER_HOME_DIR/apps/#{application}"
  set :use_sudo, false # 非Root用户
  set :keep_releases, 5 # 保留最近5个已发布的版本,清除其他的旧版本
 
  role :web, "[your-server]"  # 如果是使用Capistrano,那么这里是localhost
  role :app, "[your-server]"
  role :db,   "[your-server]", :primary => true # 表示这是一个主数据库

接下来在deploy.rb文件的末尾,找到如下几行,并去掉注释。用来在每次发布时生成一
个restart文件,使到Passenger在下次请求到来时自动重启加载应用。
 
  # 创建任务
  namespace :deploy do
    task :start do ; end
    task :stop do ; end
    task :restart, :roles => :app, :except => { :no_release => true } do
              run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
    end
  end
==================================================


【14. 创建部署环境并部署】
==================================================  
在完成配置后,可以通过cap -T 来列出所有支持的命令。可以通过如下命令来安装应用

  cap deploy:setup  # 该命令会产生大量的输出,构建标准的部署结构,类似于Maven
 
这个命令会进行如下的输出:

  $USER_HOME_DIR/apps/$APP_NAME/releases              # 存放发布的版本文件
  $USER_HOME_DIR/apps/$APP_NAME/shared                # 存放版本间共享的文件
  $USER_HOME_DIR/apps/$APP_NAME/shared/system    # 存放系统间共享的文件
  $USER_HOME_DIR/apps/$APP_NAME/shared/log          # 符号链接存放多个版本的日志
  $USER_HOME_DIR/apps/$APP_NAME/shared/pids        #  存放当前应用的pid
 
并修改所有目录的读写权限,在完成部署环境的搭建后,可以执行如下命令真正地部署

  cap deploy
==================================================  

 
【15. 自动运行bundle install】
==================================================
在将源代码部署到服务器之后,并不会自动地执行bundle install,所以需要让这一过程
自动化,在config/deploy.rb文件的头部添加如下代码:

$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
require 'rvm/capistrano'
require 'bundler/capistrano'

第一行代码将RVM的lib目录加入到加载路径中,所以Capistrano知道去哪里找bundle,
然后分别加入rvm和bundler对capistrano的支持。

在更新了这个文件后,需要重新执行一次cap deploy,将自动安装所需的gem
==================================================


【16. 配置生产环境的数据库】
==================================================
当完成源代码的部署后,接下来需要同步的就是数据库的结构。通过下列命令来完成:

  cap deploy:migrations
 
注意:这个是手动完成的。在此之前必须检查Gemfile中的DB设置是否匹配,否则会默认
创建SQLite3数据库。可以在Gemfile中(注意:是在Gemfile中,而不是database.yaml)添加

  groupd :production do
    gem 'pg' # 该gem会安装一个PostgreSQL数据库的适配器,以连接到PostgreSQL数据库
  end

如果这次之前已经部署了代码,需要用Git重新提交

  git add Gemfile*
  git commit -m "Added pg gem for PostgreSQL on the server"
  git push  
 
可以在服务器的部署目录的共享目录下,创建一个共享的数据库配置文件,让多个应用共享。
首先以vagrant用户连接登录到服务器,执行sudo su USER_NAME 切换到App发布用户,
执行

  cd /home/PATH_TO_APP/apps/APP_NAME/shared
  mkdir config
  cd config
  nano database.yml # 用vim或者其他编辑器打开编辑该文件
 
在这个文件中我们指定Production环境下的DB配置

  production:
    adapter: postgresql
    database: DB_NAME
    min_messages: warning

现在需要让应用的数据库配置文件指向这个shared/的文件,修改config/deploy.rb这个文件,
定义一个新的task,将应用的DB链接配置指向这个文件

  task :symlink_database_yml do
    # 删除原有的数据库配置文件
    run "rm #{release_path}/config/database.yml"
    # 创建软链接指向新的配置文件
    run "ln -sfn #{shared_path}/config/database.yml  #{release_path}/config/database.yml"
  end
  after "bundle:install", "symlink_database_yml"  # 在bundle install后执行这个task

在修改了本地的任何代码,资源,DB后,为了确保本地和服务器的同步,我们简单地
运行如下命令:

  cap deploy:migrations
 
这个命令会将本地代码的修改同步到服务器端,运行bundle命令,然后运行rake db:migrate
保证代码,包依赖,DB结构的同步
=================================================


【17. 验证数据库配置是否成功】
=================================================
在经过一系列的配置后,可以使用如下方法来验证应用的部署是否成功

首先以App部署用户的身份登录到服务器,进入到App发布的目录下

  cd /home/ticketeeapp.com/apps/ticketee/current  # App应用的当前运行目录
  rake db:seed RAILS_ENV=production                      # 导入测试数据到PRD环境
  psql                                                                         # 连接到PostgreSQL数据库
  psql>SELECT * FROM projects;                                # 执行SQL查询

如果我们可以看到关于App应用的信息,那么证明数据库的部署是正确的。
=================================================


【18. 安装Nginx+Passenger】
==================================================
Nginx和Passenger分别是反向代理服务器和Rails的服务器。其中Passenger提供了一个
用于和Nginx集成的模块,可以在安装该模块之前先安装Nginx。

在Console下执行命令如下:

  # Make sure we have the right ruby selected
  rvm use ree@release
  # Install the passenger gem
  gem install passenger
  # Run the passenger installer
  rvmsudo passenger-install-nginx-module

在安装Nginx的passenger模块的过程中,会出现对话提示,按照提示操作即可完成安装

注意:如果安装的Passenger是3.0以上版本,将不再需要将passenger_ruby的路径换成
passenger_ruby了,而是使用:/.rvm/wrappers/ree-1.8.7-2011.03@release/ruby

接下来让Nginx在系统启动时自动启动Passenger,这是通过一个脚本来做到的:

  sudo bash -c 'curl -L http://bit.ly/nginx-ubuntu-init-file > /etc/init.d/nginx'  
  sudo chmod +x /etc/init.d/nginx
  sudo update-rc.d nginx defaults
  sudo /etc/init.d/nginx start
==================================================


【19. 部署Rails应用】
==================================================
在安装了Nginx + Passenger之后,部署一个Rails 应用将变得非常容易。只需要在Nginx
的配置文件:/opt/nginx/conf/nginx.conf中添加这样一个“server block”

   server {
      listen 80;
      server_name www.yourhost.com;
      root /somewhere/public;   # <--- be sure to point to 'public'!
      passenger_enabled on;
   }

注意一定要将root指向Rails应用的public目录。在添加这个配置之后,Passenger将自动
识别相关的文件,并以此作为配置Gemset的依据
==================================================


【参考资料】
==================================================
Rails 3 in Action》的第14章:Deployment
RVM installation 官方文档
A Guide to a Nginx, Passenger and RVM Server


-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
posted on 2011-11-21 16:22 Paul Lin 阅读(1674) 评论(0)  编辑  收藏 所属分类: RoR

只有注册用户登录后才能发表评论。


网站导航:
 
<2011年11月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

常用链接

留言簿(21)

随笔分类

随笔档案

BlogJava热点博客

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜