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

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

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

答案

免责声明:我写了 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 附加到计算机或转发端口,并且无论使用什么系统(VirtualBox,VMware 等),配置都是相同的。对于同步文件夹,Vagrant 提供了多种机制来获取本地文件。文件转移到远程计算机(VirtualBox 共享文件夹,NFS,rsync,Samba [插件] 等)。如果您使用的是 Docker,甚至是具有不带 Vagrant 的 VM 的 Docker,则在这种情况下,您必须手动执行此操作,否则他们将不得不重新发明 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。在大多数情况下,情况并非如此。 Vagrant 不会妨碍您使用 Docker;它实际上会尽力使体验更加流畅。如果您发现这不是真的,我很乐意提出改进建议,因为 Vagrant 的目标是在任何系统上均能正常工作。

希望这可以清除一切!

我是 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 的角度来看,这是很有意义的:容器不只是另一种机器吗?就像 Amazon EC2 和 VMware 一样,我们必须小心不要将我们的配置工具绑定到任何特定的供应商!这将创建锁定 - 最好使用 Vagrant 将其抽象化。除此之外,这完全忽略了 Docker 的要点。 Docker 不配置机器;它将您的应用程序包装在轻巧的可移植运行时中,该运行时可放在任何地方。

您为应用程序选择的运行时与配置机器的方式无关!例如,经常将应用程序部署到由其他人预配的机器上(例如,由系统管理员部署的 EC2 实例,也许使用 Vagrant),或者将其部署到 Vagrant 根本无法预配的裸机上。相反,您可以使用 Vagrant 来配置与开发应用程序无关的机器 - 例如,即用型 Windows IIS 盒之类的东西。或者,您可以使用 Vagrant 为不使用 Docker 的项目配置机器 - 例如,它们可以使用 rubygems 和 rvm 的组合进行依赖性管理和沙箱管理。

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

如果您的目的是隔离,那么我认为 Docker 是您想要的。

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

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

您可能要使用 Vagrant 的唯一原因是,如果需要在 Ubuntu 机器上进行 BSD,Windows 或其他非 Linux 开发。否则,选择 Docker。

作为我的回答的开头,我承认我没有使用 Docker 的经验,只是作为一个狂热的观察者,这看起来像是一种非常整洁的解决方案,并且吸引了很多人。

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

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

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

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

它们是非常互补的。

我将 VirtualBox,Vagrant 和 Docker 的组合用于我的所有项目已有几个月,并且强烈感受到了以下好处。

在 Vagrant 中,您可以完全取消任何 Chef 单人配置,而您需要做的 vagrant 文件仅是准备一台运行单个安装 docker 的小型 shell 脚本的机器。这意味着我对每个项目的 Vagrantfiles 几乎相同且非常简单。

这是一个典型的 Vagrantfile

# -*- 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 开发环境

Vagrant-lxcVagrant的插件,让您使用 LXC 来配置 Vagrant。它没有默认游民虚拟机(VirtualBox)具有的所有功能,但与 Docker 容器相比,它应该具有更大的灵活性。链接中有一个视频,显示了其功能,值得观看。

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

请注意,您还可以将 Docker 与 Vagrant 一起使用。这与使用 Docker 作为提供程序非常不同。 http://docs.vagrantup.com/v2/provisioning/docker.html

这意味着您可以用 Docker 替换ChefPuppet 。您可以使用诸如 Docker 作为提供者(VM)和 Chef 作为预配者的组合。或者,您可以使用 VirtualBox 作为提供者,而使用 Docker 作为预配者。

两者都使用是应用程序交付测试的重要组成部分。我才刚刚开始接触 Docker,并非常认真地考虑一个应用程序团队,该团队在构建和交付其软件方面具有极其复杂的条件。想想经典的 Phoenix 项目 / 持续交付情况。

这种想法是这样的:

  • 拿一个 Java / Go 应用程序组件并将其构建为容器(请注意,不确定应用程序应该在容器中构建还是先构建然后安装到容器中)
  • 将容器交付给 Vagrant VM。
  • 对所有应用程序组件重复此操作。
  • 迭代要编码的组件。
  • 持续测试对由 Vagrant 管理的 VM 的交付机制
  • 知道何时该部署容器时,请熟睡,与 Docker 之前相比,集成测试的持续性要高得多。

这似乎是米切尔(Mitchell)的说法的逻辑延伸,该说法是 “流浪者” 是用于发展的,并结合了 “持续交付” 中的 Farley / Humbles 思维。如果我作为开发人员能够缩小关于集成测试和应用程序交付的反馈循环,那么将会出现更高质量和更好的工作环境。

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

因此,我将 Vagrant 演变为一种利用 Docker 对应用程序部署产生的可怕后果的方式。

绝对是 Docker 的胜利!

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

当然,这是一门应对自己的难题和挑战的新学科。

如果您的需求超出了单机资源限制,请选择 Docker Swarm。

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

结论

与传统 VM 相比,Docker 的轻量级容器速度更快,并且已成为开发人员和 CD 和 DevOps 计划的一部分而受到欢迎。如果您的目的是隔离,那么 Docker 是一个绝佳的选择。 Vagrant 是一个 VM 管理器,使您可以编写单个 VM 的配置脚本并进行配置。但是,这仍然是依赖 VirtualBox 的 VM(或另一个 VM 管理器)的开销较大。它要求您使硬盘驱动器空闲,该硬盘驱动器可能很大,需要大量 RAM,并且性能可能欠佳。 Docker 通过 LXC 使用内核 cgroup 和名称空间隔离。这意味着您使用与主机和相同的 ile 系统相同的内核。在抽象性方面,Vagrant 比 Docker 高一个级别,因此它们实际上没有可比性。配置管理工具(例如 Puppet)被广泛用于供应目标环境。使用 Docker 可以轻松重用现有的基于 Puppet 的解决方案。您还可以分割您的解决方案,以便 Puppet 可以配置基础结构。中间件,业务应用程序本身或两者都由 Docker 预置; Docker 由 Vagrant 包装。借助这些工具,您可以根据自己的情况做最好的事情。

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