用 Vagrant 快速建立開發環境

這次要談談如何建立開發環境。

理想的開發環境

如果你曾經做過一些十人以上、持續一年以上的專案,你就會知道開發環境的重要性。我以前就待過一個專案:專案有 J2EE Server、RDBMS 還有外部的 legacy 系統。雖然開始時很好地設定了 Development、UAT 和 Production 環境,但經歷漫長的開發和改版,Development 環境的資料總是爛的:

  • 一些被改動到不合 constraint 的資料
  • 一些設定是錯誤的
  • 有時缺少了重要的 Data
  • 沒有運行的 server 或 backend job
  • 開發者的錯誤會讓 DB 或 Apps 全爛了,整隊人得花一天以上等待修復。。。

在開發的時候,我們需要的是一個快速建立、可以重現、一步到位而且每個開發者獨立的開發環境。這時候 Vagrant 就可以幫到我們了。

30 秒內學會使用 Vagrant

Vagrant 是一個 ruby 寫的工具,它是一個 DSL 讓開發者可以輕易控制 VirtualBox 的 VM 。用它可以輕鬆管理和制作我們理想中的開發環境。

如何使用 Vagrant?假設你已安裝 ruby 和 VirtualBox,安裝 Vagrant 很簡單:

$ gem install vagrant
$ vagrant box add ubuntu http://files.vagrantup.com/lucid32.box
$ vagrant init ubuntu
$ vagrant up
  1. gem install vagrant 安裝 vagrant
  2. vagrant box add 安裝新的 Vagrant Package。這裡的 ubuntu 是一個預先做好的空的 ubuntu 10.04 。
  3. vagrant init ubuntu 在當前的位置建立一個 ubuntu VM
  4. vagrant up 啟動 VM

就這樣 Vagrant 就設定好一個基本的 VM,並將當前目錄映射到 VM 的 /vagrant 之上。通常Vagrant Box 也會把 sudo 設為不用密碼,在開發時這會省許多事。

當然了,只有一個空白的 VM 沒甚麼用。Vagrant 可以做到的事有更多。

設定和包裝自己的 VM

Vagrant 已設定好 SSH,只要使用指令 vagrant ssh 就可以連線進 VM。

你可以 SSH 進去當普通的 VM 一樣設定系統,如安裝 language 、runtime 、library、database server 、memcached 、web server 等等。

Vagrant 支援自動化設定 VM ,你可以用 old school 的 shell script ,或者用 Chef 或 Puppet 自動化設定系統。Chef 和 Puppet 有許多深入的用法和設定,你要到他們的網站研究才行。如果我的情況,人手 ssh 進 VM 設定就夠用了。

好了假設你己安裝好開發環境,因為你主機的當前的目錄已映射到 /vagrant ,如果你當前目錄是 rails project ,你只需修改 config.xml 再 rails s 就可以享受成果了。

當你確認開發環境無誤,只要用指令 vagrant package 就可以將整個環境打包成 package.box 。放到網路上,其他人就可以用 vagrant box add the-url 指令安裝你的開發環境。

自訂 Vagrant Box

在 vagrant init 的時候,Vagrant 會建立一個設定檔 Vagrantfile:

Vagrant::Config.run do |config|  
  config.vm.box = "base"
  # config.vm.forward_port "http", 80, 8080
end  

vm.forward_port 會讓 vagrant 把 VM 的 port forward 到主機之上,我會設定如下:

Vagrant::Config.run do |config|  
  config.vm.box = "base"
  config.vm.forward_port "rails", 3000, 3000
  config.vm.forward_port "mongo", 27017, 27017
  config.vm.forward_port "mongo-http", 28017, 28017
  config.vm.forward_port "redis", 6379, 6379
  config.vm.forward_port "memcached", 11211, 11211
end  

這樣 VM 的 server 就可以在主機存取,而在 VM 3000 port 行的 rails 也可以在主機用 localhost:3000 看到效果。

有時候我們需要進一步設定主機,例如行一些 migration 或更新資料,我們可以用 Vagrant 的 provisioning 行 shell script:

Vagrant::Config.run do |config|  
  config.vm.box = "base"
  config.vm.provision :shell, :path => "test.sh"
  config.vm.provision :shell, :inline => "echo foo > /vagrant/test"
end  

之後在 vagrant up 或 vagrant reload 時,VM 就會自動執行那個 shell script 了。Vagrant 還有很多的設定,請細閱他們的 Tutorial。但只是以上的基本,相信已經可以避免許多因為開發環境的杯具了。

如果你還在共用開發環境,或在開發的 mac 上裝上不同版本的 mysql, mongodb, couchdb, memcached ,不妨試試用 Vagrant 簡化你的工作流程吧!

補記 (12-21-2011)

Vagrant 可以在 Windows 下使用。如果是 32 bit Windows 可以用 Ruby Installer的 ruby。如果是 64 bit Windows 則注意要用 1.8.7 的 64 bit JRuby