我使用 Ubuntu 进行开发和部署,并且需要创建一个隔离的环境。
为此,我正在考虑使用 Vagrant 或 Docker。有什么优点和缺点,或者这些解决方案如何比较?
免责声明:我写了 Vagrant!但是因为我写了 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,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!),它充当容器的包装器。一旦安装,这是完全透明的;您可以以完全相同的方式使用 Docker 命令行。这为您提供了两全其美的优势:您可以使用容器测试和开发您的应用程序,这些容器非常轻量级、易于测试且易于移动(参见https://hub.docker.com以共享可重复使用的容器) Docker 社区),并且您不必担心管理虚拟机的细节,这只是达到目的的一种手段。
理论上,可以使用 Vagrant 作为 Docker 的抽象层。我建议不要这样做,原因有两个:
首先,对于 Docker,Vagrant 不是一个好的抽象。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 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 单独配置,您所需要做的就是准备一台机器,该机器运行一个安装 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-lxc是 Vagrant 的一个插件,可以让你使用 LXC 来配置 Vagrant。它没有默认的 vagrant VM (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替换Chef或Puppet 。您可以使用 Docker 作为提供者 (VM) 和 Chef 作为配置者的组合。或者您可以使用 VirtualBox 作为提供者,使用 Docker 作为供应者。
两者都使用是应用程序交付测试的重要组成部分。我才刚刚开始涉足 Docker,并且非常认真地思考一个应用程序团队,该团队在构建和交付其软件方面非常复杂。想想一个经典的凤凰项目/持续交付情况。
想法是这样的:
这似乎是 Mitchell 的声明的逻辑延伸,即 Vagrant 是为了开发与 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 使用内核 cgroups 和命名空间隔离。这意味着您使用与主机相同的内核和相同的文件系统。Vagrant 在抽象方面比 Docker 高出一个级别,因此它们没有可比性。Puppet 等配置管理工具广泛用于配置目标环境。使用 Docker 可以轻松重用现有的基于 Puppet 的解决方案。您还可以对您的解决方案进行切片,以便使用 Puppet 配置基础架构;中间件、业务应用程序本身或两者都使用 Docker 进行配置;并且 Docker 由 Vagrant 包装。使用这一系列工具,您可以做最适合您的场景的事情。
如何在 DevOps 中构建、使用和编排 Docker 容器 http://www.javamagazine.mozaicreader.com/JulyAug2015#&pageSet=34&page=0