我应该使用Vagrant还是Docker来创建隔离环境?

vagrant docker


我使用Ubuntu进行开发和部署,有创建一个隔离环境的需求。

为此,我正在考虑使用Vagrant或Docker。这些方案的优缺点是什么,或者说这两个方案的对比如何?





Answer 1 creack


如果你的目的是隔离,我认为Docker就是你想要的。

Vagrant是虚拟机经理。它允许您编写虚拟机配置和配置脚本。但是,它仍然是依赖VirtualBox(或其他)的虚拟机,具有巨大的开销。它要求您拥有一个巨大的硬盘文件,需要大量内存,并且性能可能不是很好。

另一方面,Docker通过LXC使用内核cgroup和命名空间。这意味着您使用与主机相同的内核和相同的文件系统。您可以将Dockerfile与docker docker build 命令一起使用,以处理容器的置备和配置。您在docs.docker.com上有一个有关如何制作Dockerfile的示例;这是非常直观的。

唯一可以使用Vagrant的原因是,如果你需要在Ubuntu的盒子上进行BSD、Windows或其他非Linux开发,那么你可以使用Vagrant。否则,请使用Docker。




Answer 2 Mitchell


免责声明:我写了Vagrant!但是因为我写了Vagrant,所以大部分时间都花在DevOps世界中,其中包括Docker之类的软件。我与许多使用Vagrant的公司合作,许多使用Docker,并且我看到两者之间如何相互作用。

在我谈论太多之前,一个直接的答案是:在您的特定情况下(您自己工作,在Linux上工作,在生产中使用Docker),您可以单独使用Docker并简化事情。在许多其他情况下(我将进一步讨论),这并不是那么容易。

直接拿Vagrant和Docker做比较是不正确的。在某些情况下,它们确实有重叠,而在绝大多数情况下,它们没有重叠。实际上,更贴切的比较应该是Vagrant和Boot2Docker这样的东西(可以运行Docker的最小化操作系统)。Vagrant 在抽象方面比 Docker 高一个层次,所以在大多数情况下,这并不是一个公平的比较。

Vagrant出于开发目的启动运行应用程序/服务的事物。这可以在VMware的VirtualBox上。它可以像AWS,OpenStack一样是远程的。在这些容器中,如果您使用容器,则Vagrant不在乎,并接受它:例如,它可以自动安装,下拉,构建和运行Docker容器。在Vagrant 1.6中,Vagrant具有基于docker的开发环境,并支持在Linux,Mac和Windows上以与Vagrant相同的工作流程使用Docker。 Vagrant在这里没有尝试替换Docker,而是采用了Docker实践。

Docker专门运行Docker容器。如果你直接和Vagrant进行比较的话:具体来说,它是一个比较特殊的(只能运行Docker容器),灵活性较差(需要Linux或Linux主机的某个地方)的解决方案。当然,如果你说的是生产型或者CI,那就没有Vagrant可以比的! Vagrant并不生活在这些环境中,所以应该使用Docker。

如果你的组织只为他们的所有项目运行Docker容器,并且只有开发人员在Linux上运行,那么好吧,Docker绝对可以为你工作!

否则,我不认为尝试单独使用Docker会有什么好处,因为你会失去很多Vagrant所能提供的东西,而这些东西有真正的商业生产力的好处。

  • Vagrant可以启动VirtualBox、VMware、AWS、OpenStack等机器。不管你需要什么,Vagrant都可以启动它。如果你正在使用Docker,Vagrant可以将Docker安装在其中任何一个机器上,这样你就可以为此目的使用。

  • Vagrant是你所有项目的单一工作流程。或者换个说法,不管项目是否在Docker容器中,它只是人们必须要学会的一件事,来运行一个项目。比如说,如果将来出现了竞争对手,直接和Docker竞争,Vagrant也能运行。

  • Vagrant可以在Windows(回到XP)、Mac(回到10.5)和Linux(回到内核2.6)上工作。在这三种情况下,工作流程都是一样的。如果你使用Docker,Vagrant可以启动一个可以在这三个系统上运行Docker的机器(VM或远程)。

  • Vagrant知道如何配置一些高级的或非高级的东西,比如联网和同步文件夹。比如说,Vagrant知道如何将静态IP附加到机器上或者转发端口。Vagrant知道如何在机器上附加一个静态IP或转发端口,无论你使用什么系统(VirtualBox、VMware等),配置都是一样的。如果你使用的是Docker,甚至是没有Vagrant的虚拟机的Docker,那么你就必须手动操作,否则他们在这种情况下必须重新发明Vagrant。

  • Vagrant 1.6对基于docker的开发环境提供了一流的支持。这不会在Linux上启动虚拟机,而会在Mac和Windows上自动启动虚拟机。最终结果是,在所有平台上使用Docker都是统一的,而Vagrant仍然处理诸如网络,同步文件夹等繁琐的细节。

为了解决我听到的具体反驳意见,我听到的是支持使用Docker而不是Vagrant。

  • "它的活动部件较少"--是的,如果你在每个项目中都专门使用Docker的话,可以这样做。即使是这样,也是在为Docker的锁定而牺牲了灵活性。如果你曾经决定不在任何项目中使用Docker,不管是过去、现在还是未来,那么你会有更多的活动部件。如果你曾经使用过Vagrant,那么你就会有那个支持其他的活动部件。

  • "它的速度更快!"-一旦你有了可以运行Linux容器的主机,Docker在运行容器方面绝对比任何虚拟机启动都要快。但是启动一个虚拟机(或远程机)是一次性的成本。在一天的时间里,大多数Vagrant用户从未实际销毁过他们的虚拟机。对于开发环境来说,这是一个奇怪的优化。在生产环境中,Docker真正闪耀的地方,我理解快速旋转更新容器的需求。

我希望现在可以清楚地看到,这是很难的,而且我相信是不正确的,将Docker与Vagrant进行比较。对于开发环境,Vagrant更抽象,更笼统。Docker(以及你可以让它像Vagrant一样的各种方式)是Vagrant的一个具体用例,而忽略了Vagrant的其他一切。

总结:在高度特定的用例中,Docker肯定是可以替代Vagrant的。但在大多数用例中,它并不是。Vagrant不会阻碍你对Docker的使用,它实际上是在尽力让你的使用体验更顺畅。如果你觉得这不是真的,我很乐意接受改进的建议,因为Vagrant的目标是在任何系统中都能同样出色地工作。

希望这能把事情弄清楚!




Answer 3 Solomon Hykes


我是《Docker》的作者。

简单的答案是,如果你想管理机器,你应该使用Vagrant。而如果你想构建和运行应用环境,你应该使用Docker。

Vagrant是一个管理虚拟机的工具。Docker是一种通过将应用程序打包成轻量级容器来构建和部署应用程序的工具。一个容器可以容纳几乎所有的软件组件及其依赖关系(可执行文件、库、配置文件等),并在一个有保证的、可重复的运行时环境中执行。这使得您可以非常容易地构建一次应用程序并在任何地方部署-在您的笔记本电脑上进行测试,然后在不同的服务器上进行实时部署等。

一个常见的误解是,您只能在Linux上使用Docker。那是不对的。您还可以在Mac和Windows上安装Docker。在Mac上安装时,Docker会捆绑一个微型Linux VM(磁盘上有25 MB!),该VM充当容器的包装器。安装后,它是完全透明的;您可以以完全相同的方式使用Docker命令行。这为您提供了两全其美的优势:您可以使用容器进行测试和开发应用程序,这些容器非常轻巧,易于测试并且易于移动(例如,参阅https://hub.docker.com,以与以下人员共享可重复使用的容器: Docker社区),您无需担心管理虚拟机的细节,这只是达到目的的一种手段。

理论上来说,使用Vagrant作为Docker的抽象层是可以的。我建议反对这样做,原因有二。

  • 首先,Vagrant对于Docker来说并不是一个好的抽象。Vagrant是为了管理虚拟机而设计的。Docker是为了管理应用运行时而设计的。这意味着,Docker在设计上,可以以更丰富的方式与应用程序进行交互,并且拥有更多关于应用程序运行时的信息。Docker中的基元是进程、日志流、环境变量和组件之间的网络链接。Vagrant 中的基元是机器、块设备和 ssh 密钥。Vagrant只是坐在堆栈中较低的位置,它唯一能与容器交互的方式就是假装它只是另一种机器,你可以 "启动 "和 "登录"。所以,当然,你可以用Docker插件键入 "vagrant up",就会有漂亮的事情发生。它能代替Docker所能做的全部广度吗?试着用原生Docker几天,你自己看看吧 :)

  • 第二,锁定论点。"如果你把Vagrant作为一个抽象,就不会被锁定在Docker中!"。从Vagrant的角度来看,这句话完全有道理:容器不就是另一种机器吗?就像亚马逊EC2和VMware一样,我们一定要注意不要把我们的供应工具与任何一个厂商捆绑在一起! 这样做会造成锁定----最好是用Vagrant把这一切抽象化掉。只是这样做完全错过了Docker的重点。Docker并不供应机器,它将你的应用程序包裹在一个轻量级的可移植运行时中,可以丢弃在任何地方。

你为你的应用程序选择什么样的运行时,与你如何配置机器无关。例如,将应用程序部署到由别人配置的机器上(例如由您的系统管理员部署的EC2实例,可能是使用Vagrant),或者部署到Vagrant根本无法配置的裸机上。相反,你可以使用Vagrant来配置与开发应用程序无关的机器--比如一个现成的Windows IIS盒子之类的。或者你也可以用Vagrant来为不使用Docker的项目提供机器--也许他们使用rubygems和rvm的组合来进行依赖管理和沙盒管理。

总结:Vagrant是用于管理机器,而Docker是用于构建和运行应用环境。




Answer 4 Chris Bushell


在回答之前,我承认我对Docker没有任何经验,只是作为一个狂热的观察者,我对这个看起来非常好的解决方案没有任何经验,而这个解决方案正在获得很大的牵引力。

我对Vagrant确实有相当丰富的经验,可以强烈推荐它。就基于VM而不是基于LXC而言,这无疑是一个更重量级的解决方案。但是,我发现一台不错的笔记本电脑(8 GB RAM,i5 / i7 CPU)可以在使用Vagrant / VirtualBox以及开发工具的情况下运行VM。

Vagrant真正很棒的事情之一是与Puppet / Chef / shell脚本的集成,用于自动配置。如果使用这些选项之一来配置生产环境,则可以创建一个开发环境,该开发环境几乎与要获得的完全相同,而这正是您想要的。

Vagrant的另一个好处是,你可以将你的Vagrant文件和你的应用程序代码一起版本。这意味着你的团队中的每个人都可以共享这个文件,你可以保证每个人都使用相同的环境配置。

有趣的是,Vagrant和Docker实际上可能是互补的。Vagrant可以扩展为支持不同的虚拟化提供程序,而Docker可能是这样的提供程序之一,不久的将来会获得支持。有关该主题的最新讨论,请参见https://github.com/dotcloud/docker/issues/404




Answer 5 Mark Stratmann


两者是非常相辅相成的。

几个月来,我一直在使用VirtualBox、Vagrant和Docker的组合来完成我的所有项目,并强烈地感受到了以下好处。

在Vagrant中,你可以完全不需要任何Chef的solo provisioning,你需要你的vagrant文件所要做的就是准备一台机器,运行一个安装docker的小shell脚本。这意味着,我的Vagrant文件在每个项目中几乎都是一样的,非常简单。

下面是一个典型的流浪者档案

# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "mark2"
  config.vm.box_url = "http://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box"
  [3000, 5000, 2345, 15672, 5672, 15674, 27017, 28017, 9200, 9300, 11211, 55674, 61614, 55672, 5671, 61613].each do |p|
    config.vm.network :forwarded_port, guest: p, host: p
  end
  config.vm.network :private_network, ip: "192.168.56.20"
  config.vm.synced_folder ".", "/vagrant", :type => "nfs"
  config.vm.provider :virtualbox do |vb|
    vb.customize ["modifyvm", :id, "--memory", "2048"]
    vb.customize ["modifyvm", :id, "--cpus", "2"]
  end
  # Bootstrap to Docker
  config.vm.provision :shell, path: "script/vagrant/bootstrap", :privileged => true
  # Build docker containers
  config.vm.provision :shell, path: "script/vagrant/docker_build", :privileged => true
  # Start containers
  # config.vm.provision :shell, path: "script/vagrant/docker_start", :privileged => true
end

安装docker的Bootstrap文件看起来是这样的

#!/usr/bin/env bash
echo 'vagrant  ALL= (ALL:ALL) NOPASSWD: ALL' >> /etc/sudoers
apt-get update -y
apt-get install htop -y
apt-get install linux-image-extra-`uname -r` -y
apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list
apt-get update -y
apt-get install lxc-docker -y
apt-get install curl -y

现在,我有一个docker_start脚本,看起来是这样的

#!/bin/bash
cd /vagrant
echo Starting required service containers
export HOST_NAME=192.168.56.20
# Start MongoDB
docker run --name=mongodb --detach=true --publish=27017:27017 --publish=28017:28017 dockerfile/mongodb
read -t5 -n1 -r -p "Waiting for mongodb to start..." key
# Start rabbitmq
docker run --name=rabbitmq --detach=true --publish=5671:5671 --publish=5672:5672 --publish=55672:55672 --publish=15672:15672 --publish=15674:15674 --publish=61613:61613 --env RABBITMQ_USER=guest --env RABBITMQ_PASS=guest rabbitmq
read -t5 -n1 -r -p "Waiting for rabbitmq to start..." key
# Start cache
docker run --name=memcached --detach=true --publish=11211:11211  ehazlett/memcached
read -t5 -n1 -r -p "Waiting for cache to start..." key
# Start elasticsearch
docker run --name=elasticsearch --detach=true --publish=9200:9200 --publish=9300:9300 dockerfile/elasticsearch
read -t5 -n1 -r -p "Waiting for elasticsearch to start..." key
echo "All services started"

在这个例子中,我正在运行MongoDB、Elastisearch、RabbitMQ和Memcached。

非Docker Chef的单人配置将相当复杂。

最后一个大的加分项是,当你转入生产时,将开发环境转化为一个由主机组成的基础架构,而这些主机都是一样的,它们只是有足够的配置来运行docker,这意味着工作确实很少。

如果你有兴趣的话,我在我自己的网站上有一篇关于开发环境的详细文章,网址是

实施Vagrant Docker开发环境