使用 Vagrant 统一开发环境实践

在服务器端开发过程中,比较痛苦的是在多个人员进行开发时,容易因为环境不统一等等的情况,容易出现传说中的 “我这儿能跑,换个环境就出问题” 的情况。我们在项目开发过程中大量的使用了 Python 语言构建 Web 类型服务。Python 对于某些需要编译的扩展模块,可能在不同的场景下带来不同的影响(如编译不过等等、二进制版本不同等等问题)。

在处理这种多人协作的环境统一问题时,我们选择 Vagrant+VirtualBox+CentOS 虚拟环境方案统一开发环境,避免出现切换开发者,切换开发环境带来的不统一的麻烦。

初始化项目

vagrant 可以在 https://www.vagrantup.com/ 下载安装,对应的系统镜像可以在 http://www.vagrantbox.es/ 找到下载安装。根据国内实际的下载情况,我们建议先行下载镜像方式初始化项目。在选择镜像时,建议选择与线上服务器版本相同的镜像。下面我们仅演示本地加载镜像方式。

下载 vagrant 和镜像后,安装 vagrant 软件。这样就可以在命令行中执行相关指令。还有,记得安装 VirtualBox。

1
vagrant box add centos /path/to/centos-6.6-x86_64.box

比如我们线上服务器使用了 centos 环境,我们在开发时,也是选择相同版本的 CentOS box。

接下来进入对应的项目目录,使用如下命令创建 Vagrantfile(centos 是刚刚添加的 box)。当然,如果项目已经存在 Vagrantfile,则可以进行省略。

1
vagrant init centos

项目文件夹下会生成 Vagrantfile 文件。

Vagrantfile 编辑

Vagrant 在执行环境初始化时会根据 Vagrantfile 文件的描述进行。比较常见的编辑内容一般包含以下几种。

如果想要使用 IP 访问该虚拟服务器,可以通过删除

:private_network, ip: "192.168.33.10"``` 前的 “#”,将该设置生效。注意需要确认 ip 不要被占用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

如果需要同步文件夹到虚拟机中(比如项目文件夹),可以注释掉 ```config.vm.synced_folder "../data", "/vagrant_data"``` 前的 “#”,将设置生效。该命令可以切换更复杂的设置:```config.vm.synced_folder "./", "/var/www", create: true, group: "nginx", owner: "nginx"``` 命令表示将本地的当前目录映射到 ```/var/www``` 目录,若不存在时创建,同意 user 和 group 设置为 nginx。

## 服务器初始化

服务器初始化功能也算是在 Vagrantfile 编辑之中的,之所以单独介绍,是因为服务器的环境是初始化时一个更加独立的过程,应用也最多。在 vagrant 环境初始化时,可以通过 Vagrantfile 的 ```config.vm.provision "shell"``` 功能,初始化服务器配置和一些基础运行环境。比如说我们现在正在使用的配置如下(Vagrantfile 中对应内容):

```ruby
config.vm.provision "shell", inline: <<-SHELL
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-6.repo
sudo yum install -y zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel
sudo yum install -y mysql-server mysql-client mysql-devel
sudo yum install -y make gcc gcc-c++
cd /tmp
wget https://www.python.org/ftp/python/2.7.11/Python-2.7.11.tgz
tar zxvf Python-2.7.11.tgz
cd /tmp/Python-2.7.11
./configure --prefix=/usr/local --with-ensurepip=upgrade
make
sudo make install
sudo /usr/local/bin/pip install virtualenv
virtualenv /mnt/pyenv
sudo /usr/local/bin/virtualenv /mnt/pyenv
source /mnt/pyenv/bin/activate
sudo /mnt/pyenv/bin/pip install -r /vagrant/requirements.txt
SHELL

该项配置使用了阿里云的 CentOS 源,编译 Python 2.7.11 并且安装应用必须的一些依赖。项目默认路径会安装在 / vagrant / 目录下,可以通过其他形式,安装至与线上环境相同的位置。

Vagrant 也支持使用

形式部署服务,如果你了解具体的使用方法,可以使用下面的形式指定 playbook。
1
2
3
4
5
6
7
8
9
10
11
12

```ruby
Vagrant.configure(2) do |config|

#
# Run Ansible from the Vagrant Host
#
config.vm.provision "ansible" do |ansible|
ansible.playbook = "playbook.yml"
end

end

当然,利用 Vagrant 也可以很方便的学习和测试

1
2
3
4
5
6
7
8

## 运行测试

在编辑 Vagrantfile 完成后,可以通过 ```vagrant up``` 命令,启动虚拟环境。此时如果设置了服务器初始化,会在最开始过程中执行大量的初始化操作。待操作完成后,则可以验证。

## 打包分发

在编辑完成后,则可以根据当前版本生成 Box 文件。对其他开发者而言,可以通过 Box 文件直接快速生成开发环境,也避免了还需要进行服务器初始化阶段。

vagrant package

1
2

输出会提示保存文件地址:

==> default: Attempting graceful shutdown of VM…
==> default: Clearing any previously set forwarded ports…
==> default: Exporting VM…
==> default: Compressing package to: /path/to/package.box

1
2
3
4
5
6

如果进行了初始化环境的变更,我们建议同时更新 Vagrantfile 文件,通过重新打包的方式进行同步更新。

## Vagrant 其他命令

在刚刚提到的几个命令中,```vagrant up``` 可以用于开启环境,对应的还有一些其他命令:

vagrant ssh // ssh
vagrant halt // 关机
vagrant status // 查看状态
vagrant destory // 删除虚拟机,如果你需要重新开始

`