【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 becausegroup 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文件分为publickey和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