我使用Ubuntu进行开发和部署,需要创建一个独立的环境。

为此,我正在考虑Vagrant或Docker。优缺点是什么,或者这些解决方案如何比较?


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

Vagrant是一个虚拟机管理器。它允许您编写虚拟机配置以及资源调配的脚本。然而,它仍然是一个依赖VirtualBox(或其他)的虚拟机,开销巨大。它需要你有一个巨大的硬盘文件,它需要很多内存,而且性能可能不是很好。

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

如果您需要在Ubuntu上进行BSD、Windows或其他非Linux开发,那么您可以使用Vagrant。否则,去找Docker。


我在回答的开头承认,除了作为一个狂热的观察者,我对Docker没有任何经验,因为它看起来是一个非常整洁的解决方案,并获得了很多关注。

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

Vagrant真正伟大的一点是与Puppet/Chef/shell脚本的集成,以实现自动配置。如果您使用这些选项之一来配置您的生产环境,那么您可以创建一个与您将要获得的几乎完全相同的开发环境,这正是您想要的。

Vagrant的另一个优点是,您可以将Vagrant文件与应用程序代码一起进行版本化。这意味着团队中的其他所有人都可以共享此文件,并且保证每个人都使用相同的环境配置。

有趣的是,Vagrant和Docker实际上可能是互补的。Vagrant可以扩展到支持不同的虚拟化提供商,Docker可能就是其中一个在不久的将来获得支持的提供商。看见https://github.com/dotcloud/docker/issues/404最近关于该主题的讨论。


Vagrant lxc是Vagrant的一个插件,让您使用lxc来提供Vagrant。它没有默认流浪VM(VirtualBox)所具有的所有功能,但它应该比docker容器更灵活。链接中有一段视频显示了它的功能,值得观看。


免责声明:我写了《流浪者》!但因为我写了Vagrant,我大部分时间都生活在DevOps世界,其中包括Docker这样的软件。我与许多使用Vagrant的公司合作,许多使用Docker,我看到了两者之间的相互作用。

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

直接比较Vagrant和Docker是不正确的。在某些情况下,它们确实重叠,而在绝大多数情况下,却没有重叠。实际上,比较Vagrant和Boot2Docker(可以运行Docker的最小操作系统)更合适。在抽象方面,Vagrant比Docker高一级,因此在大多数情况下,这不是一个公平的比较。

Vagrant为开发目的启动运行应用程序/服务的功能。这可以在VirtualBox、VMware上实现。它可以像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,Vagrannt可以在其中任何一个上安装Docker,这样你就可以使用它们了。Vagrant是所有项目的单一工作流。或者换一种说法,无论项目是否在Docker容器中,这只是人们必须学会的一件事。例如,如果未来有一个竞争对手直接与Docker竞争,Vagrant也能做到这一点。Vagrant适用于Windows(回到XP)、Mac(回到10.5)和Linux(回到2.6内核)。在这三种情况下,工作流程是相同的。如果您使用Docker,Vagrant可以启动一台机器(VM或远程),在这三个系统上都可以运行Docker。Vagrant知道如何配置一些高级或非小事,如网络和同步文件夹。例如:Vagrant知道如何将静态IP连接到机器或转发端口,并且无论您使用什么系统(VirtualBox、VMware等),配置都是相同的。对于同步文件夹,Vagrant提供多种机制将本地文件连接到远程机器(VirtualBox共享文件夹、NFS、rsync、Samba[plugin]等)。如果您使用Docker,即使Docker有一个没有Vagrant的VM,您也必须手动执行此操作,否则在这种情况下,他们将不得不重新创建Vagrant。Vagrant 1.6对基于docker的开发环境具有一流的支持。这不会在Linux上启动虚拟机,而是在Mac和Windows上自动启动虚拟机。最终结果是,在所有平台上使用Docker都是统一的,而Vagrant仍然处理诸如网络、同步文件夹等繁琐的细节。

为了解决我听到的支持使用Docker而不是Vagrant的具体反论点:

“这是不太容易移动的部分”-是的,如果你在每个项目中都专门使用Docker的话,这是可能的。即便如此,它也在牺牲Docker锁定的灵活性。如果你决定不在任何项目中使用Docker,无论是过去、现在还是将来,那么你会有更多的活动部分。如果你使用了Vagrant,那么你有一个活动的部分来支撑其余的部分。“它更快!”-一旦你有了可以运行Linux容器的主机,Docker在运行容器方面肯定比任何虚拟机都要快。但启动虚拟机(或远程机)是一次性成本。在一天中,大多数Vagrant用户实际上从未销毁过他们的VM。对于开发环境来说,这是一种奇怪的优化。在Docker真正发光的生产环境中,我理解快速旋转容器的必要性。

我希望现在可以清楚地看到,将Docker与Vagrant进行比较是非常困难的,我认为这是不正确的。对于开发环境,Vagrant更抽象,更通用。Docker(以及你可以让它像Vagrant一样的各种方式)是Vagrant的一个特定用例,忽略了Vagrant提供的所有其他功能。

总之:在高度特定的用例中,Docker当然是Vagrant的可能替代品。在大多数用例中,情况并非如此。含糊并不妨碍你使用Docker;实际上,它会尽其所能使体验更顺畅。如果你发现这不是真的,我很乐意接受改进建议,因为Vagrant的目标是在任何系统中都能同样良好地工作。

希望这能把事情弄清楚!


我是Docker的作者。

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

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

一个常见的误解是,您只能在Linux上使用Docker。这是不正确的;您也可以在Mac和Windows上安装Docker。当安装在Mac上时,Docker捆绑了一个小型Linux VM(磁盘上有25 MB!),作为容器的包装器。一旦安装,这是完全透明的;您可以以完全相同的方式使用Docker命令行。这让你两全其美:你可以使用容器来测试和开发你的应用程序,容器很轻,很容易测试,也很容易移动(参见示例https://hub.docker.com用于与Docker社区共享可重用容器),并且您不必担心管理虚拟机的具体细节,无论如何,这只是实现目标的一种手段。

理论上,可以使用Vagrant作为Docker的抽象层。我反对这种做法有两个原因:

首先,Vagrant不是Docker的好抽象。Vagrant旨在管理虚拟机。Docker旨在管理应用程序运行时。这意味着Docker在设计上可以以更丰富的方式与应用程序交互,并拥有更多关于应用程序运行时的信息。Docker中的原语是进程、日志流、环境变量和组件之间的网络链接。Vagrant中的原语是机器、块设备和ssh密钥。Vagrant只是位于堆栈的较低位置,它与容器交互的唯一方式是假装它只是另一种机器,您可以“启动”和“登录”。所以,当然,你可以用Docker插件键入“floatint up”,就会发生一些很好的事情。它是否可以替代Docker所能做的全部工作?尝试本地Docker几天,自己看看:)第二,锁定争论。“如果你使用Vagrant作为抽象,你就不会被锁定在Docker中!”。从设计用于管理机器的Vagrant的观点来看,这很有道理:容器不就是另一种机器吗?就像Amazon EC2和VMware一样,我们必须小心不要将我们的资源调配工具与任何特定的供应商绑定!这会造成锁定-最好用Vagrant将其抽象化。但这完全忽略了Docker的观点。Docker不提供机器;它将您的应用程序包装在一个轻量级的可移植运行时中,该运行时可以放在任何地方。

为应用程序选择的运行时与如何配置机器无关!例如,将应用程序部署到由其他人提供的机器上(例如,系统管理员部署的EC2实例,可能使用Vagrant),或者部署到Vagrant根本无法提供的裸机上是非常常见的。相反,您可以使用Vagrant来提供与开发应用程序无关的机器,例如一个随时可用的Windows IIS盒或其他东西。或者,您可以使用Vagrant为不使用Docker的项目提供机器——例如,它们可能使用rubygems和rvm的组合进行依赖管理和沙盒。

总之:Vagrant用于管理机器,Docker用于构建和运行应用程序环境。


使用两者是应用程序交付测试的重要部分。我才刚开始接触Docker,并非常努力地思考一个在构建和交付软件方面非常复杂的应用程序团队。想象一个典型的菲尼克斯项目/持续交付情况。

思路大致如下:

将Java/Go应用程序组件构建为容器(注意,不确定应用程序是应该在容器中构建还是在安装到容器上)将容器交付给Vagrant VM。对所有应用程序组件重复此操作。对要进行代码编写的组件进行迭代。持续测试Vagrant管理的VM的交付机制睡个好觉,知道什么时候该部署容器了,集成测试比Docker之前更为持续。

这似乎是米切尔在《持续交付》中关于Vagrant是为了发展与Farley/Humbles思维相结合的说法的逻辑延伸。如果我作为一名开发人员,能够缩小集成测试和应用程序交付的反馈回路,那么更高质量和更好的工作环境将随之而来。

作为一名开发人员,我一直在不断地向VM交付容器,并更全面地测试应用程序,这意味着生产版本将进一步简化。

因此,我认为Vagrant是一种利用Docker对应用程序部署带来的一些可怕后果的方式。


它们非常互补。

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

在Vagrant中,您可以完全取消任何Chef单独提供,您所需要的流浪文件只需准备一台运行安装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,这意味着几乎没有什么工作。

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

实现Vagrant/Docker开发环境


现在使用Vagrant,您可以将Docker作为提供者。http://docs.vagrantup.com/v2/docker/.Docker提供程序可以用来代替VirtualBox或VMware。

请注意,您也可以使用Docker为Vagrant提供资源。这与使用Docker作为提供者非常不同。http://docs.vagrantup.com/v2/provisioning/docker.html

这意味着你可以用Docker代替Chef或Puppet。您可以使用Docker作为提供者(VM)和Chef作为提供者的组合。或者您可以使用VirtualBox作为提供程序,Docker作为提供程序。


在实际的Oracle Java杂志上有一篇关于将Docker与Vagrant(和Puppet)结合使用的文章,内容非常丰富:

结论

Docker的轻量级容器比经典VM更快并在开发人员中流行,成为CD和DevOps的一部分主动性。如果你的目的是隔离,Docker是一个很好的选择。Vagrant是一个VM管理器,它使您能够编写单个VM以及进行资源调配。然而,它是窗台虚拟机依赖于VirtualBox(或另一个虚拟机管理器)大开销。它要求您将硬盘闲置巨大,它需要大量的RAM,并且性能可能不是最佳的。Docker公司通过LXC使用内核cgroups和命名空间隔离。这意味着您使用的内核与主机和文件系统相同。Vagrant在抽象方面比Docker高一级,因此它们是不是真正可比的。配置管理工具,如Puppet广泛用于供应目标环境。重用现有资源使用Docker,基于木偶的解决方案很简单。您还可以将解决方案,因此基础设施配备了Puppet;这个提供中间件、业务应用程序本身或两者与Docker合作;Docker被Vagrant包裹。使用此范围工具,您可以做最适合您的场景的事情。

如何在DevOps中构建、使用和协调Docker容器http://www.javamagazine.mozaicreader.com/JulyAug2015#&pageSet=34&page=0


肯定是Docker赢了!

您可能知道Vagrant用于虚拟机管理,而Docker用于软件容器管理。如果您不知道其中的区别,这里是:软件容器可以与其他软件容器共享相同的机器和内核。使用容器可以节省资金,因为您不会在多个操作系统(内核)上浪费资源,您可以为每台服务器打包更多的软件,保持良好的隔离度。

当然,这是一门新学科,需要关注自身的缺陷和挑战。

如果您的需求超过单机资源限制,请使用Docker Swarm。