Vagrant 快速创建 VirtualBox 虚拟机

前言

本文将介绍如何使用 Vagrant 在 VirtualBox 中快速创建 Linux 虚拟机,请提前在 Linux/Windows 本地操作系统里安装好 VirtualBox 虚拟机软件。

Vagrant 介绍

Vagrant 简介

Vagrant 是一个基于 Ruby 的开源工具,用于创建和部署虚拟化开发环境。Vagrant 可与 Hyper-V、VirtualBox、VMWare、Parallels 和 Libvirt 等虚拟化软件配合使用,致力于提供一种简易的方法来创建、配置和复制状态已知的虚拟机。它可以很方便地将预配置的虚拟机或设备从 Vagrant Cloud(镜像仓库)获取,并初始化后在系统上运行。简而言之,Vagrant 可以通过命令行快速创建 VirtualBox、VMWare 等虚拟机,主要用途类似 Docker(本质上的实现原理不一样)。

Vagrant 站点资源

Vagrant 安装

Linux 系统

Linux 系统执行以下命令安装 Vagrant 后,在终端输入命令 vagrant,若出现相关命令提示,则说明 Vagrant 安装成功。

特别注意

Linux 系统环境下,Vagrant 的虚拟机镜像下载目录是 ~/.vagrant.d,为了方便日后有足够的磁盘空间安装更多的虚拟机镜像,建议通过软链接的方式更改镜像存放的默认目录,例如: ln -sf /your_new_path ~/.vagrant.d

Fedora

1
2
3
$ sudo dnf install -y dnf-plugins-core
$ sudo dnf config-manager --add-repo https://rpm.releases.hashicorp.com/fedora/hashicorp.repo
$ sudo dnf -y install vagrant

CentOS/RHEL

1
2
3
$ sudo yum install -y yum-utils
$ sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
$ sudo yum -y install vagrant

Debian/Ubuntu

1
2
3
$ wget -O- https://apt.releases.hashicorp.com/gpg | gpg --dearmor | sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg
$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
$ sudo apt update && sudo apt install vagrant

Windows 系统

Vagrant 官网 下载 EXE 安装包,然后直接安装即可。Vagrant 安装完成后,打开 CMD 窗口,输入命令 vagrant,若出现相关命令提示,则说明安装成功。

Vagrant 常用命令

命令描述
vagrant box add 添加 box 的操作
vagrant box list 查看本地的 box 列表
vagrant box remove 删除本地的 box
vagrant init 初始化 box 的操作,会生成 Vagrant 的配置文件 Vagrantfile
vagrant up 启动本地虚拟机
vagrant ssh 通过 SSH 登录本地虚拟机
vagrant suspend 暂停本地虚拟机
vagrant resume 恢复本地虚拟机
vagrant package 将当前本地虚拟机打包成 box
vagrant status 查看当前虚拟机的状态
vagrant global-status 显示当前用户下 Vagrant 所有虚拟机的状态
vagrant reload 更改了 Vagrantfile 后,使之生效(相当于先 halt,再 up)

Vagrant 创建虚拟机

创建 VirtualBox 虚拟机

执行以下 init 命令,即可快速初始化一个 VirtualBox 虚拟机。值得一提的是,虚拟机初始化完成后,Vagrant 会在执行命令的当前目录下创建一个 Vagrantfile 文件。

1
vagrant init centos/7

命令行中的 centos/7 代表需要初始化 CentOS 7 的虚拟机,如果需要初始化其他虚拟机直接替换它就可以,注意 / 符不能省略掉,例如初始化 Ubuntu 虚拟机的命令如下:

1
vagrant init ubuntu/trusty64

提示

Vagrant 支持的虚拟机列表可以在右边这个网站查找到:https://app.vagrantup.com/boxes/search

启动 VirtualBox 虚拟机

执行以下 up 命令,即可快速启动上面初始化好的 VirtualBox 虚拟机

1
vagrant up

Vagrant 首次启动 VirtualBox 虚拟机时,会从 Vagrant Cloud(镜像仓库)下载对应的镜像,CentOS 7 虚拟机完整的启动日志信息如下:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Box 'centos/7' could not be found. Attempting to find and install...
default: Box Provider: virtualbox
default: Box Version: >= 0
==> default: Loading metadata for box 'centos/7'
default: URL: https://vagrantcloud.com/centos/7
==> default: Adding box 'centos/7' (v2004.01) for provider: virtualbox
default: Downloading: https://vagrantcloud.com/centos/boxes/7/versions/2004.01/providers/virtualbox.box
Download redirected to host: cloud.centos.org
default: Calculating and comparing box checksum...
==> default: Successfully added box 'centos/7' (v2004.01) for 'virtualbox'!
==> default: Importing base box 'centos/7'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'centos/7' version '2004.01' is up to date...
==> default: Setting the name of the VM: Vagrant_default_1663582821802_96925
==> 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: 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: 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: No guest additions were detected on the base box for this VM! Guest
default: additions are required for forwarded ports, shared folders, host only
default: networking, and more. If SSH fails on this machine, please install
default: the guest additions and repackage the box to continue.
default:
default: This is not an error message; everything may continue to work properly,
default: in which case you may ignore this message.
==> default: Rsyncing folder: /home/centos/vagrant/ => /vagrant

SSH 连接 VirtualBox 虚拟机

VirtualBox 虚拟机系统启动后,Vagrant 会为我们自动创建 SSH 连接,因此我们不仅可以直接通过 VirtualBox 操作虚拟机系统,也可以通过 SSH 连接来操作。Vagrant 默认的 SSH 账号名称是 vagrant,登录密码是 vagrant,所以可以通过这种连接方式以 Vagrant 的账号连接虚拟机系统,命令如下:

1
vagrant ssh

使用 SSH 连接到 VirtualBox 虚拟机系统后,若希望切换到 root 用户,可以在终端输入下命令,root 用户的默认密码是 vagrant

1
$ su root

VirtualBox 虚拟机网络配置

默认情况下,Vagrant 创建虚拟机后,使用的是网络地址转换和端口转发的方式来解决本地系统和虚拟机网络地址映射的问题,如下图所示。在实际使用过程中,网络地址转换和端口转发的方式可能不太方便。举个例子,在虚拟机中装了很多软件服务,比如 MySQL 数据库,Redis 等等,在虚拟机内部使用是没有问题的。MySQL 数据库的端口默认是 3306,但在本地系统中,虚拟机给我们映射出来的端口可能就不是 3306 了,这对于在本地系统上进行测试是及其不方便的。因此,若不希望使用这种默认的方式,可以设置一个私有的 IP 实现本地系统和虚拟机系统之间的互通。

在本地系统(宿主机)内执行以下命令,找到 VirtualBox 的虚拟网卡地址,例如 192.168.56.2

1
$ ip addr

或者

1
$ ifconfig -a

编辑 Vagrantfile 文件,找到如下的一行内容,去掉注释并更改 IP 地址,例如 192.168.56.10。特别注意,其中的网段 192.168.56 是固定的,而 10 可以换成其他的,最大不要超过 255 就可以

1
config.vm.network "private_network", ip: "192.168.56.10"

重新加载 Vagrantfile 配置文件,Vagrant 会自动重启虚拟机系统

1
vagrant reload

虚拟机系统重启完成后,在本地系统和虚拟机之间互相执行 Ping 操作,如果互相能 Ping 得通,说明网络配置成功,操作步骤如下:

  • 在虚拟机中 Ping 本地系统的 IP 地址
1
ping 192.168.56.2
  • 在本地系统中 Ping 虚拟机的 IP
1
ping 192.168.56.10

VirtualBox 虚拟机硬件资源配置

由于 Vagrant 创建 VirtualBox 虚拟机时,默认只会分配较少的处理器(CPU)和内存资源,因此需要在 VirtualBox 的用户界面里手动更改虚拟机的硬件资源配置,如下图所示:

VirtualBox 虚拟机启用账号密码登录

Vagrant 创建的 VirtualBox 虚拟机默认只支持 SSH 登录方式,为了后续操作方便,比如上传文件或者 SSH 远程连接,可以配置允许使用账号密码登录,步骤如下:

  • 编辑 sshd 服务的配置文件
1
$ sudo vi /etc/ssh/sshd_config
  • PasswordAuthentication 改为 yes
1
PasswordAuthentication yes
  • 重启 sshd 服务
1
$ sudo service sshd restart

Vagrant 打包 Box

为了方便将本地的虚拟机备份或者分发到互联网上,可以将让 Vagrant 将虚拟机打包成 Box 文件。

特别注意

  1. 在执行打包命令之前,建议将 Vagrantfile 配置文件中的虚拟网络配置注释掉,否则以后通过添加 Box 的方式恢复虚拟机时,虚拟机可能会无法正常启动
  2. 例如,在执行打包命令之前,注释掉 Vagrantfile 配置文件中的 config.vm.network "private_network", ip: "192.168.56.10"

打包命令

  • 命令格式:vagrant package --base {packagename} --output {/path/packagename.box}
  • 命令参数:--base:当前本地要打包的虚拟机,--output:打包导出的文件的路径,{packagename}:Box 的包名(唯一标识)

打包示例

  • 查看虚拟机列表
1
vboxmanage list vms
  • 虚拟机列表如下
1
2
"php-centos7" {4b663e7c-ba60-4026-9330-64c2e6d6d1c4}
"java-centos7" {7b1cf3a0-72e0-4d47-9a93-6aae4c701390}
  • 打包虚拟机
1
vagrant package --base php-centos7 --output ./php-centos7.box

Vagrant 添加 Box

从互联网上下载或者本地虚拟机打包得到的 Box 文件,可以通过 Vagrant 命令将 Box 添加到本地,然后就可以创建并启动对应的虚拟机,这类似 备份 --> 恢复

添加命令

  • 命令格式:vagrant box add {packagename} {/path/packagename.box}
  • 命令参数:{packagename}:Box 的包名(唯一标识),{/path/packagename.box}:Box 文件的本地路径

添加示例

1
2
3
4
5
6
7
8
# 添加本地的 Box
vagrant box add php-server-centos7 ./php-centos7.box

# 创建虚拟机
vagrant init php-server-centos7

# 启动虚拟机
vagrant up

提示

1、vagrant box add 命令除了可以指定 Box 文件的本地路径之外,还可以指定 Box 文件的网络地址(镜像源 URL),借此就可以加快镜像的下载速度
2、若是 Vagrant 添加的是本地虚拟机导出的 Box 文件,那么创建虚拟机后,一般还需要在 VirtualBox 的界面上手动更改虚拟机的 Mac 地址,否则虚拟机启动后会存在 Mac 地址冲突的问题

Vagrant 设置第三方镜像源

为了提高 Vagrant 镜像的下载速度,可以在 这里 找到自己想要的镜像源(URL),然后使用指定的镜像源来添加 Box,最后再创建并启动虚拟机。

1
2
3
4
5
6
7
8
# 使用指定的镜像源(URL)来添加 Box
vagrant box add {packagename} {url}

# 创建虚拟机
vagrant init {packagename}

# 启动虚拟机
vagrant up

CentOS 7 虚拟机系统配置

若安装的是 CentOS 7 虚拟机,可以执行以下操作来配置虚拟机操作系统(可选操作)。值得一提的是,以下操作都需要以 root 用户身份执行。

更换 YUM 源

1
2
3
4
5
6
7
8
9
10
11
# 备份原YUM源
# mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.bak

# 使用阿里云的YUM源
# curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

# 清理数据
# yum clean all

# 生成缓存
# yum makecache

安装 EPEL 源

1
# yum install -y epel-release

安装常用软件

1
# yum install -y vim tree htop tmux net-tools telnet wget curl

时间自动同步

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 由于Centos7默认使用chronyd来同步时间,如果需要安装其他时间同步服务(ntpd),则需要禁用chronyd
# systemctl disable chronyd

# 安装ntp服务
# yum install -y ntp

# 开机启动ntp服务
# systemctl enable ntpd

# 启动ntp服务
# systemctl start ntpd

# 查看ntp服务的运行状态
# systemctl status ntpd
1
2
3
4
5
6
7
8
9
10
11
# 使用ntp手动同步时间
# ntpdate pool.ntp.org

# 设置亚洲时区
# timedatectl set-timezone Asia/Shanghai

# 启用ntp同步
# timedatectl set-ntp yes

# 查看当前系统时间、时间同步状态
# timedatectl status

安装 Docker

  • Docker 安装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 卸载旧版本的Docker
# yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine

# 添加YUM仓库
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 安装Docker
# yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 开机启动Docker
# systemctl enable docker

# 启动Docker
# systemctl start docker

# 查看运行状态
# systemctl status docker
  • Docker 镜像加速

针对 Docker 客户端版本大于 1.10.0 的用户,可以通过修改 daemon 的配置文件 /etc/docker/daemon.json 来使用阿里云的镜像加速。值得一提的是,使用阿里云的镜像加速之前,需要在阿里云平台注册账号,并开通容器镜像服务

1
2
3
4
5
# 创建配置文件的目录
# mkdir -p /etc/docker

# 创建配置文件,并写入以下JSON内容
# vi /etc/docker/daemon.json
1
2
3
{
"registry-mirrors": ["https://xxxxx.mirror.aliyuncs.com"]
}
1
2
3
4
5
# 重载配置文件
# systemctl daemon-reload

# 重启Docker
# systemctl restart docker

提示

上述 https://xxxxx.mirror.aliyuncs.com 链接,是开通阿里云的镜像服务之后得到的。

常见问题

打包虚拟机后无法恢复运行

问题描述

  • 打包虚拟机后,通过添加 Box 的方式让虚拟机恢复运行,但虚拟机在启动时一直卡在 SSH auth method 阶段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'Vagrant-Gulimall-CentOS7'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: centos7
==> 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: 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: vagrant
default: SSH auth method: private key

解决方案

  • 第一种方案:在执行打包命令之前,将 Vagrantfile 配置文件中的虚拟网络配置注释掉(如下),然后再执行打包命令
1
# config.vm.network "private_network", ip: "192.168.56.10"
  • 第二种方案:虚拟机恢复运行失败后,往 Vagrantfile 配置文件添加以下配置内容,然后重新启动虚拟机
1
2
3
config.ssh.username = "root"
config.ssh.password = "vagrant"
config.ssh.insert_key = "true"
  • 第三种方案:将要打包的虚拟机所在目录下的 private_key 秘钥文件(路径如下)复制一份,并拷贝覆盖到要恢复运行的虚拟机所在目录下,然后重新启动虚拟机
1
/xxxx/.vagrant/machines/default/virtualbox/private_key
  • 第四种方案:如果虚拟机还是无法正常启动,可以使用 --debug 参数来获取详细的启动日志信息
1
$ vagrant up --debug

相关资料

虚拟机挂载共享目录失败

问题描述

  • 虚拟机启动时,提示无法挂载 VirtualBox 的共享目录
1
2
3
4
5
6
7
8
9
10
11
12
Vagrant was unable to mount VirtualBox shared folders. This is usually
because the filesystem "vboxsf" is not available. This filesystem is
made available via the VirtualBox Guest Additions and kernel module.
Please verify that these guest additions are properly installed in the
guest. This is not a bug in Vagrant and is usually caused by a faulty
Vagrant box. For context, the command attempted was:

mount -t vboxsf -o uid=0,gid=0,_netdev vagrant /vagrant

The error output from the command was:

mount: unknown filesystem type 'vboxsf'

解决方案

  • 先将 VirtualBox 虚拟机关闭掉
1
$ vagrant halt
  • 执行以下命令安装 vagrant-vbguest 插件
1
$ vagrant plugin install vagrant-vbguest
1
2
3
4
Installing the 'vagrant-vbguest' plugin. This can take a few minutes...
Fetching micromachine-3.0.0.gem
Fetching vagrant-vbguest-0.31.0.gem
Installed the plugin 'vagrant-vbguest (0.31.0)'!
  • 插件安装完成后,重新启动虚拟机
1
$ vagrant up
  • 虚拟机正常启动后,建议执行以下命令卸载插件(可选操作)
1
$ vagrant plugin uninstall vagrant-vbguest

在卸载插件时,可以忽略 Vagrant 输出的错误信息,然后使用以下命令查看插件是否成功卸载

1
$ vagrant plugin list

相关资料

参考博客