Vagrant|Vagrant (四) Advanced of Box

还是看掘金吧:[HERE](https://juejin.im/post/5c75f73d6fb9a049fe35cffa)
Box 是一个 bundle 或者 package,它将一台虚拟机所需要的一切设施捆绑到一个单一的、可交换的文件之中,从而提供了分享的便利。
从这一点上说,Box 和 OVF 是一样的东西。不过 OVF 是具有公信力的标准格式,而 Box 则是 Vagrant 的私有格式。所以人们不免疑问既然如此、岂非我还是去 VMWare/VirtualBox 中导出 ovf 格式的比较好吧?事实上又并非这么简单,就好像 Microsoft Office 也是私有格式一样,它还是通行于全球。所以,一般地看,为着分享一个极为有效的基础设施的目的,你可能还是需要通过 Vagrant Box 特性建立你的基础设施的 VirtualBox/VMWare/KVM/Hyper-V 分发包,才能真的让世界上的其它人或许感谢你的友好;而如果你只是临时给LAN中某个人传递一个snapshot的话,就ovf好了;如果你的 team 统一使用 vagrant 为开发容器环境的话,那当然还是 box 了;如果你的 team 主力使用 docker,那就已经不在这个问题讨论范围内了。
## 自己的box ### 打包 VM 为 box
一般的用法是:
```bash
【Vagrant|Vagrant (四) Advanced of Box】vagrant package --base dos7bc31 --output dos7bc31.box
```
在这里,你首先在VirtualBox中制作了一个名为 dos7bc31 的虚拟机,并且在虚拟机中搭建了 DOS 7.1的环境和安装了 Borland C++ 3.1,然后发布此命令就能得到一个 box 文件了:
```bash
$ vagrant package --base dos71bc31 --output dos71bc31.box
==> dos7bc31: Exporting VM...
==> dos7bc31: Compressing package to: /Users/hz/vmt/dos7/dos71bc31.box
$ ll
total 113784
-rw-r--r--1 hzstaff3.0K Feb 21 10:05 Vagrantfile
-rw-r--r--@ 1 hzstaff55M Feb 21 10:08 dos71bc31.box
```
当然,你需要为那个虚拟机准备一份 Vagrantfile,这可以用 `vagrant init` 在当前的空文件夹中建议一份。
### 分发 box
LAN中,直接传输 box 给他人即可。
你也可以考虑发布 box 到公共目录中。
### 使用 box
对于一个本地的 box 文件,可以这样添加它:
```bash
vagrant box add --name hedzr/dos71bc31 ./dos71bc31.box
```
然后就可以初始化相应的实例了:
```bash
mkdir test && cd test1
vagrant init hedzr/doc71bc31
vagrant up
```
### 迭代
当发布了你的box的新版本之后,接收人需要更新它。对于本地的 box 文件,更新的方法是:
```bash
vagrant box add -f --name hedzr/dos72bc31 './dos71bc31 (1).box'
```
如果发布者在构建 box 时正确地进行了 `config.vm.box_version` 的管理的话,则 `-f` 标志不必使用。
## 命令和概念参考 相关的 vagrant 命令参考如下:
### package
`package` 命令用于从虚拟机提供商(例如 virtualbox)环境中已经创建了虚拟机实例中打包一个 .box 可交换文件出来。
```bash
Usage: vagrant package [options] [name|id]
Options:
--base NAMEName of a VM in VirtualBox to package as a base box (VirtualBox Only)
--output NAMEName of the file to output
--include FILE,FILE..Comma separated additional files to package with the box
--vagrantfile FILEVagrantfile to package with the box
-h, --helpPrint this help
```
### box
box 包含一组子命令:add,list,outdated,prune,remove,repackage,update。
| 命令| 描述|
| --------- | ------------------------------------------------------------ |
| add| 添加 box(从文件、url、短名字)到 vagrant boxes管理区,必要时自动下载它 |
| list| 列出 vagrant boxes 管理区中已有的本地 boxes|
| outdated| 检查本地 boxes 的时效性,有否新版本存在|
| prune| 删除本地 boxes 的旧版本,仅保留最新的一个版本|
| remove| 删除一个本地 box|
| repackage | 重新打包一个本地 box,这多用于本地创建新box的过程中|
| update| 更新一个本地 box,从远程来源|
你可以通过 `vagrant box add --help` 来获取相应的命令行参数参考。或者检查官网:[Box](https://www.vagrantup.com/docs/cli/box.html)。
为免填充字数只说,这里不再罗列了。
```bash
cd dos71bc31
vagrant package --base dos71bc31 --output dos71bc31.box --vagrantfile
vagrant box add -f --name hedzr/dos71bc31 dos71bc31.box
mkdir test1 && cd test1
vagrant init hedzr/dos71bc31
vagrant up
# shutdown VM from virtualbox ...
vagrant destroy -f
cd -
vagrant box remove hedzr/dos71bc31 -f
```
### Vagrantfile loader
按照官方的说法,Vagrantfile能够被合并。
这就是说,当你通过 `vagrant init` 建立了一个新的虚拟机环境时,vagrant将会一次检查一系列的可用的 Vagrantfile 并将它们合并到最终为你生成的 `Vagrantfile` 中。而当 `vagrant up` 当前虚拟机时,vagrant同样会检查这一系列可用的 Vagrantfile,并依据有否变更或虚拟机有否不符等实际情况对真实的虚拟机进行配置修订。
这些可用的 Vagrantfile 包括:
1. box 中自带的
2. 你在 ~/.vagrant.d/ 中自定义的一个 Vagrantfile
3. 你的当前虚拟机的 Vagrantfile。当 `vagrant init` 时,此文件尚未存在故略过,当 `vagrant up` 时它会被检视,并根据实际情况去修订虚拟机
4. 如果存在 [Multi-machine overrides](https://www.vagrantup.com/docs/multi-machine/)
5. 如果存在 [Provider-specific overrides](https://www.vagrantup.com/docs/providers/configuration.html)
可以参考:[Load Order and Merging](https://www.vagrantup.com/docs/vagrantfile/#load-order)
### GUI模式
有多种方法启用或禁用 虚拟机的 GUI 界面。
直接通过命令行:
```
vagrant up --gui
vagrant up --headless
```
修改 `Vagrantfile` 配置文件:
```ruby
config.vm.provider "virtualbox" do |v|
v.gui = true
end
```
对于大多数基于 Linux Server 的虚拟机来说,乃至于 vagrant 默认情况下,一个虚拟机总是被启动于 headless 无界面模式的。
不过即使这样,你还是可以在 VirtualBox应用程序界面中双击虚拟机缩略图或者通过虚拟机子菜单显示其 gui 界面。
有人曾钻研过这个问题,列出了一个更奇技的方法来方便你指定GUI模式与否。其方法是修改Vagrantfile加入如下片段:
```ruby
# Returns true if `GUI` environment variable is set to a non-empty value.
# Defaults to false
def gui_enabled?
!ENV.fetch('GUI', '').empty?
end
Vagrant.configure('2') do |config|
config.vm.provider 'virtualbox' do |v|
v.gui = gui_enabled?
end
end
```
然后你就可以这样来执行命令:
```bash
# for *nix system
GUI=1 vagrant up# gui mode
vagrant up# -headless mode
# for windows
SET GUI=1
vagrant up
```
See also: https://stackoverflow.com/a/23929641/6375060
不过我觉得多余。至于我列举的原因呢,只是展示一种使用环境变量的方法,它可以被用于自行装配和分发 box。

    推荐阅读