Vagrant - 打造一份通用的前端开发环境

1,612 阅读11分钟
原文链接: blog.5udou.cn

前言

最近在做一个项目的时候,手贱删了Ubuntu下的~/.*的文件,好多配置文件包括.bash_profile/.bashrc/.zshrc等重要的文件全都清空了,自己一下子懵逼了,我可都是没有备份这些文件呀呀。难道我又得重新安装一遍系统吗?

无意中,听到我们组长说起Vagrant,说是搭建开发环境是分分钟的事情,并且能够一份配置能够跨平台到处使用,不禁心动起来,于是乎就立马去试试这个Vagrant了,于是有了这篇文章。

1、Vagrant是啥?

玩转一个新鲜的东西之前,我们是有必要了解这个东西是啥?翻阅了国内国外的资料,大致明白了Vagrant的基本原理了。

在平时开发的时候,我是在虚拟机的基础上运行Ubuntu,然后这个过程中你就需要安装系统,分区、选择各种软件以及卸载掉很多无关的系统自带软件,这些过程都可以参考之前写过的几篇文章(VirtualBox简单配置Ubuntu16.04Vmware安装Ubuntu15.10),这样一套的系统完成至少得持续一个小时才能完成。最后可以移植的vmdk文件也会达到3、4G那么大。可谓是劳民伤神呀。

因此为了解决这个痛点,Vagrant应运而生。它省却了你安装系统的一切烦恼,一个box便可以解决这些问题,而且体积大大减轻,并且可以跨平台跨环境任意使用,是不是觉得很神奇呢?Vagrant的Box其实可以看成是之前你在虚拟机上安装完系统生成的Vmdk文件的一个封装(假设你的Provider是VirtualBox之类的虚拟机)

因此Vagrant可以看成是一个高级的虚拟机镜像管理器。一套完整的环境镜像称之为Box。任何人都可以制作属于自己的box。这个box就是所谓的开发环境,包含系统和相关的软件。通过vagrant方便的与虚拟机共享文件。即将宿主机的文件夹映射到虚拟机的文件系统里。还可以映射网络端口,设置通信的私有网络等。vagrant依赖与虚拟机,目前支持的虚拟化方式很多。与Virtualbox、VMware、Docker都能很好的工作。

1.1、Provider

在Vagrant看来,诸如VirtualBox这类的虚拟机都是统称为Provider

Provider 的作用是在 Vagrant 和不同虚拟化软件之间架设一座桥梁。有了 Provider,Vagrant 管理不同虚拟机软件的命令完全一致,使用更方便。现阶段的 Vagrant 不能更换已有环境的 Provider,如果你的 Vagrant 环境需要封装给其他小伙伴们用,最好使用 VirtualBox 这个支持 OSX/Linux/Win 三大宿主系统的免费软件作为后端;如果你只是自己用,并且已经装有 Parallels Desktop,那就可以使用 Parallels Provider,可以少装一个软件。顺便说下,现在 VirtualBox 和 Parallels Desktop 同时运行也没问题了。

1.2、Box

Boxes 是一个后缀为 box的文件,实际上它就是一个包含了虚拟机配置、虚拟机硬盘镜像和 Vagrant 配置的压缩包。之前在虚拟机里安装 Linux,首先需要下载 iso 安装镜像并新建虚拟机,然后修改虚拟机的 cpu、内存、光驱、网络等等硬件配置,再从光驱启动并安装虚拟机,完成后还有装虚拟机增强工具、配置系统、映射端口、映射磁盘目录等好多事要做。有了封装好的 Boxes,我们就可以快速运行所需要的操作系统了。不同 Provider 之间,Boxes 不能混用。

一个Box解压之后应该存在的文件是:

2、开始打造通用的前端开发环境

明白了Vagrant是啥,那么基于Vagrant来打造一套开发环境应该会变得有趣很多。我们不打算从头开始制作一个Box,而是使用Vagrant现有的基本Box来改造,大部分的Box可以在下面的网站上找到:

因为我一直使用的Ubuntu16,所以选择了ubuntu/xetinal16作为我们的Base Box。

2.1、下载并安装Base Box

我们首先新建一个目录:Vagrant

然后进入该目录运行如下命令:

vagrant init ubuntu/xenial64

打印如下:

A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

这个时候Vagrant会自动为你生成一个Vagrantfile文件,里面有初始化的一些配置

接着我们启动这个Base Box:

vagrant up

Vagrant会首先去搜索你的Vagrant文件目录以及默认的Box目录,在我系统上是C:\Users\Administrator\.vagrant.d\boxes,如果找到它需要的Box就可以直接启动,如果找不到那么还要去之前说的box官方网站下载box到默认的Box目录,这里我是先下载下来,所以无需去下载,整个启动过程如下:

Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/xenial64'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'ubuntu/xenial64' is up to date...
==> default: Setting the name of the VM: Vagrant_default_1488941499616_2827
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: ubuntu
    default: SSH auth method: password
    default: Warning: Remote connection disconnect. Retrying...
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Mounting shared folders...
    default: /vagrant => D:/Vagrant

如此基本的Ubuntu便启动了,前后整个过程不超过3分钟,是不是比之前系统安装的简便很多呀?

我们使用XSHELL工具通过端口2222便可以登录到Ubuntu上,记得这个时候的登录方式可以是SSH Key的也可以是密码方式的。如果是SSH Key的话,公钥就放在之前新建目录Vagrant下面:以我的为例子就是:D:\Vagrant\.vagrant\machines\default\virtualbox,如果是密码的方式,那么你就得找到这个Base Box的密码,它就放在默认的Box目录下的Vagrantfile,以卧的为例子:C:\Users\Administrator\.vagrant.d\boxes\ubuntu-VAGRANTSLASH-xenial64\20170303.1.0\virtualbox,文件内容是:

# Front load the includes
include_vagrantfile = File.expand_path("../include/_Vagrantfile", __FILE__)
load include_vagrantfile if File.exist?(include_vagrantfile)

Vagrant.configure("2") do |config|
  config.vm.base_mac = "025E4BB29711"
  config.ssh.username = "ubuntu"
  config.ssh.password = "6ce44951a49047b3d834784e"

  config.vm.provider "virtualbox" do |vb|
     vb.customize [ "modifyvm", :id, "--uart1", "0x3F8", "4" ]
     vb.customize [ "modifyvm", :id, "--uartmode1", "file", File.join(Dir.pwd, "ubuntu-xenial-16.04-cloudimg-console.log") ]
  end
end

那么密码一眼就看出来了。这里有一个坑,在后面我们会说一下。

当然我们肯定不会仅仅满足于这样的一个基础空架子,我们要修改这个box为具有前端特性的个人box。

2.2、box改造

根据官方文档的介绍,我们改写整个VagrantFile文件如下:

# -*- mode: ruby -*-
# vi: set ft=ruby :

# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|

  config.ssh.username = "root"
  config.ssh.password = "111111"
  config.ssh.insert_key = true

  config.vm.define "frontend" do |frontend|
    frontend.vm.box = "ubuntu/xenial64"
    config.vm.network "forwarded_port", guest: 3000, host: 3000
    config.vm.network "forwarded_port", guest: 3001, host: 3001
    config.vm.network "forwarded_port", guest: 9090, host: 9090
    config.vm.network "forwarded_port", guest: 9091, host: 9091
    config.vm.network "forwarded_port", guest: 9098, host: 9098
    config.vm.network "forwarded_port", guest: 9099, host: 9099
    frontend.vm.hostname = "front-linguang"
    frontend.vm.synced_folder "/ubuntuSync", "/home", create: true
    frontend.vm.provision "shell", path: "provision-frontend.sh"
  end

  config.vm.provider "virtualbox" do |vb|
  #   # Display the VirtualBox GUI when booting the machine
  #  vb.gui = true
  #
  #   # Customize the amount of memory on the VM:
    vb.memory = "2048"
  end

end

好了,解读一下配置文件:

Vagrant.configure("2") do |config|:全局配置,并且表明该配置文件的版本是2

config.vm.define "frontend" do |frontend|: 当需要启动多个box的时候你就需要这条配置,我们为了兼容以后多个机器的情况,于是使用MULTI-MACHINE的情形

config.vm.network "forwarded_port", guest: 3000, host: 3000: 配置主机和虚拟机映射的端口,也就是说当从主机访问3000端口的时候是映射到虚拟机的3000端口。

frontend.vm.hostname: 配置虚拟机中命令提示符的显示名称

frontend.vm.synced_folder "/ubuntuSync", "/home", create: true: 配置共享文件夹的目录,前者是主机的目录,后者是虚拟机的目录

frontend.vm.provision "shell", path: "provision-frontend.sh": 配置机器起来的时候自动执行的脚本,有点类似于Docker中的Dockerfile

config.vm.provider "virtualbox" do |vb|: Provider的配置,比如设置内存2G,CPU核使用几个之类的。

,每一个config之后都有一个end表示当前区块配置结束。

完成这个配置文件遇到了几个彩蛋:

第一个彩蛋是我之前是将frontend.vm.box = "ubuntu/xenial64"误写成config.vm.box = "ubuntu/xenial64",然后在后面的vagrant 操作上就会报如下错误:

刚开始还以为是Vagrant的bug,然后就手动删除.vagrant\machines目录下所有文件,貌似又恢复了,但是后来不断地测试不断的出现这个问题,就很郁闷了,然后到官网上看文档,才发现我的这种配置属于MULTI-MACHINE,它有另外一套规则的,所以才改成正确的结果

第二个彩蛋便是配置了用户名和密码:

  config.ssh.username = "root"
  config.ssh.password = "111111"
  config.ssh.insert_key = true

折腾这个搞了好久,配置完这个在vagrant up frontend的时候会一直请求你的密码:

然后我当时是以为是我配置的那个密码,后来仔细研究了一下,我使用的Base Box,这个box不是有之前提过的那个密码吗?于是乎我这样的配置在起初运行的时候是不可行的,因为用户名都是不对的,至于网上说的什么默认密码vagrant都是没啥卵用,所以有的时候自己分析会比网上靠谱些。

于是解决办法便是先注释掉那些关于SSH的配置,首先进入Base Box,然后修改一些配置,尤其是配置Root密码或者你别的用户的密码,接着再配置允许SSH以root用户登录(可以参考Vmware安装Ubuntu15.10),然后再退出,取消注释,密码修改为你之前给root用户设置的密码,再启动:

Bringing machine 'frontend' up with 'virtualbox' provider...
==> frontend: Importing base box 'ubuntu/xenial64'...
==> frontend: Matching MAC address for NAT networking...
==> frontend: Checking if box 'ubuntu/xenial64' is up to date...
==> frontend: Setting the name of the VM: Vagrant_frontend_1488958836384_70420
==> frontend: Clearing any previously set network interfaces...
==> frontend: Preparing network interfaces based on configuration...
    frontend: Adapter 1: nat
==> frontend: Forwarding ports...
    frontend: 22 (guest) => 2222 (host) (adapter 1)
==> frontend: Running 'pre-boot' VM customizations...
==> frontend: Booting VM...
==> frontend: Waiting for machine to boot. This may take a few minutes...
    frontend: SSH address: 127.0.0.1:2222
    frontend: SSH username: ubuntu
    frontend: SSH auth method: password
    frontend: Warning: Remote connection disconnect. Retrying...
    frontend:
    frontend: Inserting generated public key within guest...
    frontend: Removing insecure key from the guest if it's present...
    frontend: Key inserted! Disconnecting and reconnecting using new SSH key...
==> frontend: Machine booted and ready!
==> frontend: Checking for guest additions in VM...
==> frontend: Setting hostname...
==> frontend: Mounting shared folders...
    frontend: /home => D:/ubuntuSync
    frontend: /vagrant => D:/Vagrant
==> frontend: Running provisioner: shell...
    frontend: Running: C:/Users/ADMINI~1/AppData/Local/Temp/vagrant-shell20170308-3944-1540g23.sh
==> frontend: Start provisioning!

2.3、打造属于你自己的Provision

在第一次启动的时候,Vagrant都是会去帮你执行你provision中的配置,为了打造一款基本的前端开发环境,我们的执行脚本会去安装一些基本的包:

#!/bin/bash
echo "Start provisioning!"

echo "add some private repo(nodejs/mongoDB/ruby) to ubuntu"
sudo apt-add-repository ppa:chris-lea/node.js
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
sudo echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.2.list

echo "Ubuntu apt-get update"
sudo apt-get update

echo "Ubuntu install basic packages"
sudo apt-get install python-software-properties python g++ make software-properties-common

echo "Installing git"
sudo apt-get install -y git

echo "Installing ruby"
sudo apt-get install -y ruby-full

echo "Installing Sass"
gem install sass

echo "Installing Nginx"
sudo apt-get install -y nginx

echo "Installing MongoDB"
sudo apt-get install -y mongodb-org

echo "Installing Nodejs"
sudo apt-get install -y nodejs

echo "Installing npm"
sudo apt-get install -y npm
sudo chown -R $USER:$GROUP ~/.npm
sudo ln -s /usr/bin/nodejs /usr/bin/node

echo "Installing NRM (globally)"
sudo npm install -g nrm

echo "Swith the npm repository to taobao mirror"
sudo nrm use cnpm

echo "Installing Gulp (globally)"
sudo npm install -g gulp

echo "Installing SailsJs (globally)"
sudo npm install -g sails

echo "Upgrade nodejs to newest stable version"
sudo npm install -g n
sudo n stable

echo "Setting up gitconfig and bash_profile files"
git clone https://github.com/linxiaowu66/PersonalConfigurationFiles.git

cp PersonalConfigurationFiles/.bash_profile .bash_profile
cp PersonalConfigurationFiles/.gitconfig .gitconfig

source .bash_profile
# rm -R dotfiles/

echo "Cleaning the packages"
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*

echo "It's all done sweetheart, enjoy! ^.^"
exit

然后大功告成,这样安装下来整个box的尺寸大约是676MB,而Base Box是300MB左右,整体大小仍然是比直接安装Ubuntu少了好几倍的。

2.4、Vagrant常用命令

  1. vagrant halt frontend: 关掉frontend
  2. vagrant suspend frontend: 休眠frontend
  3. vagrant reload frontend [--provision]: 重启frontend(并强制provisioners 执行provision脚本)
  4. vagrant resume frontend: 唤醒frontend
  5. vagrant destroy frontend: 删除frontend

更多配置参考Vagrant官方文档

3、打包发布你的Vagrant

打造完你的Vagrant后想让更多人都可以使用,这个时候你就需要用下面的命令去打包这个box:

vagrant package --output ubuntu16_frontend.box --vagrantfile Vagrantfile

然后你这个文件就可以放在一些共享的网站上,比如我的这个box可以在这个网站上下载到:

https://pan.baidu.com/s/1bDPNeY
提取密码: xr47

这下子可以享受Vagrant带来的开发乐趣了。。。

参考

  1. www.vagrantup.com/docs/

本文对你有帮助?欢迎扫码加入前端学习小组微信群: