---
# System prepended metadata

title: Vagrant
tags: [VirtualBox, Vagrant]

---

## 介紹
[Vagrant](https://developer.hashicorp.com/vagrant) 可以迅速建立虛擬主機配置環境，不需要再像 Vitrual Box 將整個 OS 安裝一遍，只需要使用 [Vagrant boxes](https://developer.hashicorp.com/vagrant/docs/boxes) 就可以馬上獲得一個作業系統。在 [Vagrant Cloud](https://app.vagrantup.com/boxes/search) 上就能搜尋需要的 box 來使用，尤其官方特邊推薦 [Bento Boxes](https://app.vagrantup.com/bento) 中的 boxes，除了大部分為知名創作者外，大部分品質穩定且也都在 Github 上開源。

## 安裝
直接到 [Vagrant 官網](https://developer.hashicorp.com/vagrant/downloads)下載相對應的版本即可。
本人使用 Windows 做示範，請使用 Windows 可執行的 Bash CMD 即可。

## 示範
### 1. 版本顯示
輸入：
```
$ vagrant version
```
輸出：
```
Installed Version: 2.3.7
Latest Version: 2.3.7

You're running an up-to-date version of Vagrant!
```

### 2. 初始化 box
輸入：
```
$ mkdir ~/Desktop/workspace
$ cd ~/Desktop/workspace
$ vagrant init bento/centos-7.9
```
輸出：
```
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.
```
注意：若資料夾內已有 Vagrantfile 時則不能重複初始化新的 box。

### 3. 啟動 box
輸入：
```
$ vagrant up
```
輸出：
```
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'bento/centos-7.9' could not be found. Attempting to find and install...
    default: Box Provider: virtualbox
    default: Box Version: >= 0
==> default: Loading metadata for box 'bento/centos-7.9'
    default: URL: https://vagrantcloud.com/bento/centos-7.9
==> default: Adding box 'bento/centos-7.9' (v202303.13.0) for provider: virtualbox
    default: Downloading: https://vagrantcloud.com/bento/boxes/centos-7.9/versions/202303.13.0/providers/virtualbox.box
    default:
==> default: Successfully added box 'bento/centos-7.9' (v202303.13.0) for 'virtualbox'!
==> default: Importing base box 'bento/centos-7.9'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'bento/centos-7.9' version '202303.13.0' is up to date...
==> default: Setting the name of the VM: workspace_default_1689059864043_23910
==> default: Fixed port collision for 22 => 2222. Now on port 2200.
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2200 (host) (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2200
    default: SSH username: vagrant
    default: SSH auth method: private key
    default:
    default: Vagrant insecure key detected. Vagrant will automatically replace
    default: this with a newly generated keypair for better security.
    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: The guest additions on this VM do not match the installed version of
    default: VirtualBox! In most cases this is fine, but in rare cases it can
    default: prevent things such as shared folders from working properly. If you see
    default: shared folder errors, please make sure the guest additions within the
    default: virtual machine match the version of VirtualBox you have installed on
    default: your host and reload your VM.
    default:
    default: Guest Additions Version: 7.0.6
    default: VirtualBox Version: 6.1
==> default: Mounting shared folders...
    default: /vagrant => C:/Users/Kurt/Desktop/workspace
```
注意：因首次啟動需要下載整份 box，所以耗時會較久

### 4. ssh box
輸入：
```
$ vagrant ssh
```
輸出：
```
This system is built by the Bento project by Chef Software
More information can be found at https://github.com/chef/bento
[vagrant@localhost ~]$
```
#### 此時我們已進入這個 box 之中，而我們這次使用的系統是 CentOS 7.9。

輸入：
```
$ cat /etc/*release*
```
輸出：
```
CentOS Linux release 7.9.2009 (Core)
Derived from Red Hat Enterprise Linux 7.9 (Source)
NAME="CentOS Linux"
VERSION="7 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="7"
PRETTY_NAME="CentOS Linux 7 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:7"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-7"
CENTOS_MANTISBT_PROJECT_VERSION="7"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="7"

CentOS Linux release 7.9.2009 (Core)
CentOS Linux release 7.9.2009 (Core)
cpe:/o:centos:centos:7
```

注意：通常默認的密碼為 `vagrant`，若無法登入上網查應該也有答案。

### 5. 關閉 box
輸入：
```
$ vagrant halt
```
輸出：
```
==> default: Attempting graceful shutdown of VM...
```

### 6. 命名此 box
因預設初始化 box 時通常命名為 default，當太多 box 在執行時會產生錯亂。

輸入：
```
$ vagrant status
```
輸出：
```
Current machine states:

default                   poweroff (virtualbox)

The VM is powered off. To restart the VM, simply run `vagrant up`
```

我們只需要在 Vagrantfile 中增加 define 的設定即可。

Vagrantfile：
```
Vagrant.configure("2") do |config|
  config.vm.box = "bento/centos-7.9"
  config.vm.define "Training_for_TS"
end
```

此時再將 box up 之後就能看到 box 已更名為 Training_for_TS。

輸入：
```
$ vagrant.exe up
```
輸出：
```
Bringing machine 'Training_for_TS' up with 'virtualbox' provider...
==> Training_for_TS: Importing base box 'bento/centos-7.9'...
==> Training_for_TS: Matching MAC address for NAT networking...
==> Training_for_TS: Checking if box 'bento/centos-7.9' version '202303.13.0' is up to date...
==> Training_for_TS: Setting the name of the VM: workspace_Training_for_TS_1689061454221_81981
==> Training_for_TS: Fixed port collision for 22 => 2222. Now on port 2200.
==> Training_for_TS: Clearing any previously set network interfaces...
==> Training_for_TS: Preparing network interfaces based on configuration...
    Training_for_TS: Adapter 1: nat
==> Training_for_TS: Forwarding ports...
    Training_for_TS: 22 (guest) => 2200 (host) (adapter 1)
==> Training_for_TS: Booting VM...
==> Training_for_TS: Waiting for machine to boot. This may take a few minutes...
    Training_for_TS: SSH address: 127.0.0.1:2200
    Training_for_TS: SSH username: vagrant
    Training_for_TS: SSH auth method: private key
    Training_for_TS:
    Training_for_TS: Vagrant insecure key detected. Vagrant will automatically replace
    Training_for_TS: this with a newly generated keypair for better security.
    Training_for_TS:
    Training_for_TS: Inserting generated public key within guest...
    Training_for_TS: Removing insecure key from the guest if it's present...
    Training_for_TS: Key inserted! Disconnecting and reconnecting using new SSH key...
==> Training_for_TS: Machine booted and ready!
==> Training_for_TS: Checking for guest additions in VM...
    Training_for_TS: The guest additions on this VM do not match the installed version of
    Training_for_TS: VirtualBox! In most cases this is fine, but in rare cases it can
    Training_for_TS: prevent things such as shared folders from working properly. If you see
    Training_for_TS: shared folder errors, please make sure the guest additions within the
    Training_for_TS: virtual machine match the version of VirtualBox you have installed on
    Training_for_TS: your host and reload your VM.
    Training_for_TS:
    Training_for_TS: Guest Additions Version: 7.0.6
    Training_for_TS: VirtualBox Version: 6.1
==> Training_for_TS: Mounting shared folders...
    Training_for_TS: /vagrant => C:/Users/Kurt/Desktop/workspace
```

輸入：
```
$ vagrant status
```
輸出：
```
Current machine states:

Training_for_TS           running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.
```

### 7. 打包 box
打包 box 的目的是為了讓其他人能用完全相同的開發環境，這樣才能確保所有人都是在相同的基礎上開發。

打包需要在 box 為關機狀態下才能進行。

輸入：
```
$ vagrant package
```
輸出：
```
==> Training_for_TS: Clearing any previously set forwarded ports...
==> Training_for_TS: Exporting VM...
==> Training_for_TS: Compressing package to: C:/Users/Kurt/Desktop/workspace/package.box
```

打包完成後會出現一個新檔案 package.box，此時只需要將此 package.box 傳給其他組員，其他組員就能使用相同的環境開發。

### 8. 新增 box
當拿到 box 或 box 的 url，我們可以使用指令加入到我們的環境中。

首先我們先確認我們環境中有那些 box。

輸入：
```
$ vagrant box list
```
輸出：
```
bento/centos-7.9 (virtualbox, 202303.13.0)
```

使用指令將 package.box 加到我們的 list 中。

輸入：
```
$ vagrant box add TS_team package.box
```
輸出：
```
==> box: Box file was not detected as metadata. Adding it directly...
==> box: Adding box 'TS_team' (v0) for provider:
    box: Unpacking necessary files from: file://C:/Users/Kurt/Desktop/workspace/package.box
    box:
==> box: Successfully added box 'TS_team' (v0) for 'virtualbox'!
```

#### 注意：package.box 的位置可以是一個檔案或 url。

此時我們確認 box list 中已增加了 TS_team 這個 box。

輸入：
```
$ vagrant box list
```
輸出：
```
TS_team          (virtualbox, 0)
bento/centos-7.9 (virtualbox, 202303.13.0)
```

最後我們只需要在新的資料夾內初始化這個 box，就能得到一模一樣的開發環境了。

輸入：
```
$ mkdir ~/Desktop/TS_team
$ cd ~/Desktop/TS_team
$ vagrant init TS_team
$ vagrant status
$ vagrant ssh
```

## 結語
有時團隊在開發時可能會共用開發環境，但這其實可能並不是太好的做法，如果大家各自能拿到一模一樣的開發環境，並分別開發，最後再用各自的版本控制合在 Staging 上並測試，或許也是一個不錯的方案。

主要會想使用這個方法的契機為 TS Team 在 training 時發現各個工程師的環境不盡相同，有人使用 CentOS7，有人用 docker，也有人用 RHEL9，而此次剛好又是 DB 相關的 training，還需要各自再倒資料進 DB，耗費許多時間。若一開始準備好已倒好資料的環境給每個人使用，就可以減少前期在建置的這些時間。

原有使用 Virtual Box 的人也可以試著使用 Vagrant 看看，雖然 Vagrant 是建立在 Virtual Box 之上，但省下下載 iSO 和安裝的時間，可以利用這些時間做更多的事，也是更好的方案。