立即上手
上一節(jié)中银择,我們介紹了怎樣安裝 Vagrant孤里,安裝本身并不困難。本章節(jié)中我們首先要快速上手蝇摸,以便獲得一個(gè)直觀的概念:
建立一個(gè)工作目錄
打開命令行工具婶肩,終端工具办陷,或者iTerm2等,建立一個(gè)我們將要新建虛機(jī)的項(xiàng)目目錄律歼,例如 first-vm
:
cd $HOME
mkdir -p vms/first-vm
cd vms/first-vm
Windows的命令可能像這樣:
cd %HOME%
mkdir -p vms\first-vm
cd vms\first-vm
我們需要一個(gè)完全空白的工作目錄作為開始民镜。如上我們新建一個(gè)目錄當(dāng)做項(xiàng)目目錄的基準(zhǔn)位置。
初始化一個(gè)操作系統(tǒng)
以 Ubuntu 操作系統(tǒng)為虛擬機(jī)的例子险毁,我們可以這樣初始化:
vagrant init ubuntu/xenial64
這個(gè)命令將會(huì)去下載 ubuntu 的 box 鏡像回來制圈,然后以該鏡像為核心,在工作目錄下建立一份虛擬機(jī)規(guī)范描述文件 Vagrantfile
畔况。有關(guān)的描述我們稍后會(huì)加以介紹鲸鹦。
在這里,你需要知道的是跷跪,你可以修改或查看這個(gè)文本格式的文件馋嗜。本質(zhì)上說,Vagrantfile采用ruby等價(jià)的語(yǔ)法吵瞻,所以你可以選擇文本編輯器按照ruby進(jìn)行語(yǔ)法加亮葛菇。在啟動(dòng)這個(gè)vagrant虛機(jī)之前,可以修改Vagrantfile中的配置橡羞,例如添加更多網(wǎng)卡眯停。
啟動(dòng)虛擬機(jī)并操作它
那么,我們可以啟動(dòng)這個(gè)虛機(jī)或者關(guān)閉它:
vagrant up #啟動(dòng)虛機(jī)
vagrant halt #停止虛機(jī)
vagrant destroy [-f] #刪除虛機(jī)
刪除虛機(jī)的指令將會(huì)全部刪除虛機(jī)的后端vmm中的全部相關(guān)文件卿泽、快照等等庵朝,但并不會(huì)刪除項(xiàng)目目錄中的 Vagrantfile
。
當(dāng)虛機(jī)啟動(dòng)之后又厉,在項(xiàng)目目錄執(zhí)行命令 vagrant ssh
可以登錄到虛擬機(jī)中九府。
虛機(jī)目錄 /vagrant 和項(xiàng)目目錄是自動(dòng)同步的,在虛機(jī)中寫入/vagrant中將會(huì)在宿主機(jī)中的項(xiàng)目目錄中找到相應(yīng)的內(nèi)容覆致。
虛機(jī)是完整的 Ubuntu 操作系統(tǒng)侄旬,當(dāng)使用 vagrant ssh
登錄到虛擬機(jī)中之后,你得到了一個(gè)虛擬機(jī)的終端控制臺(tái)煌妈,現(xiàn)在你可以使用 Ubuntu 自身的shell指令了儡羔,并且可以隨時(shí)通過 exit
結(jié)束控制臺(tái)返回到宿主機(jī)的控制臺(tái)環(huán)境。
$ vagrant up
...
$ vagrant ssh
vagrant@vm1> ll /vagrant
...
vagrant@vm1> exit
$ ...
$ vagrant shutdown
使用Vagrant
常用命令
vagrant init [name [url]] # 初始化當(dāng)前目錄到 vagrant 環(huán)境
vagrant up # 啟動(dòng)虛擬機(jī)
vagrant halt # 關(guān)閉虛擬機(jī)
vagrant reload # 重啟虛擬機(jī)
vagrant status # 查看虛擬機(jī)運(yùn)行狀態(tài)
vagrant destroy [-f] # 銷毀當(dāng)前虛擬機(jī)(但不刪除Vagrantfile)
vagrant suspend # 掛起當(dāng)前虛擬機(jī)
vagrant resume # 恢復(fù)被掛起的vm
vagrant ssh # SSH 登錄至虛擬機(jī)
vagrant box add ADDRESS # 安裝box文件/url到本地
vagrant box list # 列出所有本地已安裝的box列表
vagrant box outdated # 檢查已安裝的box是否有更新的版本
vagrant box remove NAME # 刪除某個(gè)已安裝的box
vagrant package # 打包當(dāng)前虛擬機(jī)環(huán)境為box文件以用于分發(fā)
vagrant plugin # 安裝卸載vagrant插件
vagrant provision # 執(zhí)行專門的環(huán)境初始化腳本
vagrant ssh-config # 輸出ssh連接的一些信息
vagrant version # 獲取vagrant的版本
更多命令可以查看 vagrant 官方的文檔璧诵。
轉(zhuǎn)換現(xiàn)有虛擬機(jī)為box包
對(duì)于剛建立的第一個(gè)虛擬機(jī)鏡像first-vm汰蜘,它的項(xiàng)目目錄名稱為“first-vm”,并且已經(jīng)至少使用 vagrant up 啟動(dòng)過一次了之宿,那么我們現(xiàn)在可以將這個(gè)虛擬機(jī)導(dǎo)出為box包:
vagrant package --base=first-vm --output=first-vm-v1.box
這個(gè)box同樣可以被添加到本機(jī)的vagrant boxes緩存中:
vagrant box add first-vm-v1.box --name=first-vm-v1
box文件實(shí)際上是一個(gè) OVF 包族操。
開源虛擬化格式OVF文件是一種開源的文件規(guī)范,它描述了一個(gè)開源、安全色难、有效泼舱、可拓展的便攜式虛擬打包以及軟件分布格式,它一般有幾個(gè)部分組成枷莉,分別是ovf文件娇昙、mf文件、cert文件笤妙、vmdk文件和iso文件冒掌。
如果網(wǎng)絡(luò)模式中使用 private_network 的話,在打包之前需要清除一下private_network的設(shè)置蹲盘,避免不必要的錯(cuò)誤:
vm$ sudo rm -f /etc/udev/rule.d/70-persistent-net.rules
這條bash指令應(yīng)該在虛機(jī)中被執(zhí)行股毫,對(duì)于不同的操作系統(tǒng)來說,文件的位置可能是有變化的辜限。
將這個(gè)box文件分發(fā)給同事皇拣,則他們也可以創(chuàng)建一個(gè)完全等價(jià)的虛擬機(jī)。
vagrant box add first-vm-v1.box --name=myteam/first-vm-v1
vagrant init my-team/first-vm-v1
vagrant up
Vagrantfile 介紹
此前薄嫡,我們通過 vagrant init
的指令創(chuàng)建了新的虛擬機(jī)環(huán)境氧急,在工作目錄中一個(gè) Vagrantfile將被自動(dòng)創(chuàng)建,如果它尚未存在的話毫深。
這個(gè)文件通常應(yīng)該是這樣子的:
# -*- 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|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "ubuntu/xenial64"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network "private_network", ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# 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 = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
# config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# apt-get install -y apache2
# SHELL
end
這個(gè)文件的內(nèi)容很容易讀懂吩坝。
-
box
config.vm.box = "ubuntu/xenial64"
這句話是指定操作系統(tǒng)用的。換句話說哑蔫,你用文本編輯器修改它也就會(huì)隨心替換系統(tǒng)了钉寝。
只不過如果你真的要這么做的話,需要執(zhí)行
vagrant destroy; vagrant up
這樣的序列闸迷,以便清理舊的虛擬機(jī)設(shè)施和以新的虛機(jī)配置創(chuàng)建相應(yīng)的設(shè)施嵌纲。對(duì)于 VirtualBox來說,它提供了 VBoxManage 命令行工具可以針對(duì)某個(gè) VM 做很多事腥沽,
modifyvm
就是一條可以修訂 VM 配置參數(shù)的子命令逮走。而Vagrant也可以在配置文件Vagrantfile
中操作 virtualbox 以達(dá)到類似的目的。例如:config.vm.provider "virtualbox" do |v| v.customize ["modifyvm", :id, "--name", "bastion", "--memory", "2048"] end
這個(gè)示例可以修改 VM 的內(nèi)存為 2GB今阳。
-
網(wǎng)絡(luò)設(shè)置
默認(rèn)情況下师溅,vagrant通知provider創(chuàng)建 NAT 類型的網(wǎng)卡,這樣虛擬機(jī)將能夠和主機(jī)之間相互通訊盾舌,同時(shí)VM能夠借助宿主機(jī)的外網(wǎng)環(huán)境直接訪問公網(wǎng)墓臭。
在這種情況下,我們可以指定VM的端口轉(zhuǎn)發(fā)來暴露VM中的應(yīng)用程序的端口妖谴,從而在宿主機(jī)上可以直接與該端口進(jìn)行通信窿锉。config.vm.network "forwarded_port", guest: 80, host: 8080
例如,我們?cè)赩M中安裝了nginx的話,上面的端口轉(zhuǎn)發(fā)設(shè)定可以將其暴露為宿主機(jī)的 :8080 榆综,這樣我們從宿主機(jī)或者內(nèi)網(wǎng)的其他主機(jī)都可以訪問VM中的nginx服務(wù)了妙痹。
網(wǎng)絡(luò)配置是個(gè)大話題铸史,我們稍后會(huì)專列一章更多地講述幾種最佳實(shí)踐鼻疮。 -
同步文件夾
我們?cè)?jīng)提到過當(dāng) SSH 到 VM 中時(shí),/vagrant
實(shí)際上和主機(jī)的VM工作目錄是等價(jià)的琳轿,也就是Vagrantfile
所在的那個(gè)目錄判沟。這種特性實(shí)際上就是 vagrant 建立的一個(gè)同步目錄的機(jī)制。一般來說崭篡,它是通過 provider 的所謂 共享文件夾(Shared Folder)的特性來實(shí)現(xiàn)的挪哄。
我們當(dāng)然并不需要關(guān)心 provider 的特性,也不必關(guān)心 vagrant 是怎么做的琉闪。我們只需要知道迹炼,這個(gè)連接點(diǎn)是可以被自定義的:config.vm.synced_folder "../data", "/vagrant_data"
上面這一配置,會(huì)將宿主機(jī)的
VM工作目錄/../data
映射為 VM中的/vagrant_data
颠毙。
你還可以做到更多:- 同步文件夾支持符號(hào)鏈接斯入,所以你可以通過符號(hào)鏈接聚合主機(jī)的其他位置到一個(gè)root連接點(diǎn)中。
-
使用ruby循環(huán)語(yǔ)句建立多個(gè) VMs
在一個(gè)Vagrantfile配置中蛀蜜,建立一組VMs是很容易的事情:(1..3).each do |i| config.vm.define "node-#{i}" do |node| node.vm.provision "shell", inline: "echo hello from node #{i}" end end
值得注意的是刻两,使用ruby的
for i in 1..3 do
循環(huán),你無(wú)法得到想要的結(jié)果滴某。原因是for i in
語(yǔ)句在每次循環(huán)迭代時(shí)為i
賦新的值磅摹,并重用循環(huán)體的語(yǔ)句塊,這就導(dǎo)致|node|
也并不得到新的副本霎奢,而是上一次循環(huán)時(shí)的node
户誓,結(jié)果是你只能得到一個(gè)不斷修改后的單一的 VM。如下所示:# THIS DOES NOT WORK! for i in 1..3 do config.vm.define "node-#{i}" do |node| node.vm.provision "shell", inline: "echo hello from node #{i}" end end
-
替換 VM 的 Locale
一般情況下幕侠,SSH會(huì)話沿用宿主機(jī)控制臺(tái)的Locale帝美,但你可以通過預(yù)定義覆蓋它,在會(huì)話中總是使用特定的語(yǔ)言:ENV["LC_ALL"] = "en_US.UTF-8" Vagrant.configure("2") do |config| # ... end
-
Provisioning
Provisioning 也是一個(gè)大話題橙依。我會(huì)考慮單列一章证舟。
不過在這里,我們主要是提及這個(gè)機(jī)制能干些什么窗骑。
簡(jiǎn)單地說女责,Provisioning是一個(gè)首次啟動(dòng)時(shí)的后初始化點(diǎn),它發(fā)生在 VM 操作系統(tǒng)被安裝就緒创译,并首次啟動(dòng)完成時(shí)抵知。你可以編寫 Shell 腳本在這個(gè)點(diǎn)自動(dòng)完成你的專屬環(huán)境初始化動(dòng)作,例如安裝標(biāo)準(zhǔn)服務(wù)、安裝bash擴(kuò)展組件(例如git-prompt)刷喜、建立必要的工作文件夾和拉取特定的分發(fā)包之類残制。
如果有必要,在今后掖疮,即使VM已經(jīng)完成了首次初始化了初茶,你也可以通過vagrant up --provision
這樣的指令來強(qiáng)制 VM 開機(jī)和再次執(zhí)行 Provisioning 腳本。
在 Vagrantfile 中浊闪,典型地可以這樣指定 Provioning:$script = <<-SCRIPT echo I am provisioning... date > /etc/vagrant_provisioned_at SCRIPT Vagrant.configure("2") do |config| config.vm.provision "shell", inline: $script end
也可以指定一個(gè)腳本文件恼布,注意我們通過
/vagrant
傳遞 provision.sh 到 VM 中,而典型的 box 系統(tǒng)中搁宾,/vagrant
是在$PATH
搜索路徑中的:Vagrant.configure("2") do |config| config.vm.provision "shell", path: "provision.sh" end
你也可以指定腳本的全路徑名折汞,甚至可以在 path 中指定一個(gè) url。