为什么选择 Docker?
那么 Docker 到底能做什么呢?
但是虚拟机不是很慢吗?
我不能直接将我的应用程序上传到一堆云服务器上吗?
这是一个更简单的解决方案
但这对我的开发有何帮助?
总结…
了解 Docker 如何改变我们的编码方式
自 2013 年初 Docker 上线以来,程序员和系统管理员对它一直爱恨交加。虽然我采访过的一些“资深”开发人员对容器化总体上非常反感(稍后会详细介绍),但据报道,包括 eBay、Twitter、Spotify 和 Lyft 在内的许多大公司都在其生产环境中采用了 Docker,这并非没有原因。
那么 Docker 到底能做什么呢?
你用过 VMware、VirtualBox、Parallels 或其他虚拟化软件吗?Docker 的功能基本相同(虽然没有花哨的 GUI),它会创建一个虚拟机,其中包含你选择的操作系统,并且只捆绑了你的 Web 应用程序及其依赖项。
但是虚拟机不是很慢吗?
虚拟化是推动云计算革命的动力,我喜欢将 Docker 称为虚拟化的最后一步,它实际上执行您开发的业务逻辑。
但是,您说得对——典型的虚拟机速度很慢,而 Docker 的功能不能完全归类为虚拟化。相反,Docker 通过使用runc(由开放容器倡议组织维护)在内核对不同进程命名空间、设备命名空间等的支持之上提供了一个抽象,这使得它能够共享大量主机系统资源。由于 Docker 容器和主机内核之间没有额外的虚拟化层,因此容器能够提供与主机几乎相同的性能。
完全虚拟化的系统会分配一组自己的资源,并进行最少的共享(如果有的话),这会导致更多的隔离,但它更重(需要更多的资源) - 然而,使用 Docker,你会得到较少的隔离,但容器非常轻量级(需要更少的资源)。
如果您需要运行一个绝对需要完全隔离且资源有保障的系统(例如游戏服务器),那么基于 KVM 或 OpenVZ 的虚拟机可能是您的最佳选择。但是,如果您只想将不同的进程彼此隔离,并在一个规模合理的主机上运行多个进程,且不至于花费太多,那么 Docker 就是您的最佳选择。
如果您想了解更多关于运行容器化系统的性能方面的信息,可以参考 IBM 的一篇很棒的研究论文:《虚拟机与 Linux 容器的最新性能比较》(2014 年,Felter 等人),该论文对虚拟机和容器进行了深入的比较。
我不能直接将我的应用程序上传到一堆云服务器上吗?
是的,如果您不关心基础设施、环境一致性、可扩展性或可用性之类的东西,那么您可以。
想象一下以下场景:您管理着十几个 Java 服务,并将它们部署在运行 Java 8 的 Ubuntu 服务器上,分别用于开发、质量保证、预发布和生产环境。即使您尚未实现应用程序的高可用性,也至少需要管理 48 台服务器(12 个服务 x 4 个环境)。
现在想象一下,您的团队牵头制定了一项组织变更政策,要求您将运行时升级到 Java 11。这意味着您需要登录并手动更新 48 台服务器。即使使用 Chef 或 Puppet 等工具,这也是一项艰巨的工作。
这是一个更简单的解决方案
Docker 允许您创建所需操作系统的快照,并仅安装所需的依赖项。我喜欢它的一个方面是,您可以管理所有“过度软件”或缺少的软件。您可以使用 Linux 的最小安装(我推荐 Alpine Linux,但出于本文的目的,我将继续使用 Ubuntu),并在其上仅安装 Java 8。
当需要更新时,只需编辑 Java 镜像的 Dockerfile 以使用 Java 11,构建并推送到容器存储库(如 Docker Hub 或 Amazon ECR),之后您需要做的就是更改应用程序容器的基本镜像标签以引用新的快照并重新部署它们。
这是在 Ubuntu 18.04 最小操作系统上构建的示例 Docker 容器的要点。
damian
我将使用标签构建并推送此镜像到 Docker Hub 帐户oracle-jdk-ubuntu-18.04:1.8.0_191
,然后使用它来构建另一个容器以供我的服务运行:
# Instructs Docker to build this container on top of this snapshot
FROM damian/oracle-jdk-ubuntu-18.04:1.8.0_191
# Copys the application JAR to the container
COPY build/hello-world.jar hello-world.jar
# Executes this command when the container starts
CMD java -jar hello-world.jar
现在,如果我需要将服务更新到 Java 11,只需发布一个安装了兼容 JRE 的新版 Java 快照,并更新服务容器中 FROM 声明中的标签,指示容器使用新的基础镜像即可。瞧,下次部署时,您的所有服务都将使用 Ubuntu 和 Java 的最新更新。
但这对我的开发有何帮助?
好问题。
我最近开始在单元测试中使用 Docker。想象一下,你有成千上万个测试用例(如果你有的话,相信我,我感同身受),它们连接到一个数据库,每个测试类都需要一个全新的数据库副本,并且每个测试用例都会对数据执行 CRUD 操作。通常情况下,我们会在每次测试后使用类似Redgate 的Flyway之类的工具重置数据库,但这意味着你的测试必须按顺序运行,并且会耗费大量时间(我见过一些单元测试套件因此需要长达 20 分钟才能完成)。
使用 Docker,您可以轻松创建数据库镜像(我推荐使用TestContainers),在容器内为每个测试类运行一个数据库实例,然后并行运行整个测试套件。由于所有测试类都并行运行并链接到不同的数据库,因此它们可以在同一主机上同时运行,并快速完成(假设您的 CPU 能够处理)。
我发现自己使用 Docker 的另一个地方是在使用 Golang 编写代码时(我发现它的配置和依赖管理很混乱)——我没有直接在开发机器上安装 Go,而是遵循了与Konstantin Darutkin类似的方法,即维护一个 Dockerfile,其中包含我的 Go 安装 + 依赖项配置,以便在我对源文件进行更改时实时重新加载我的项目。
这样,由于我的项目和 Dockerfile 已经进行了版本控制,如果我需要更换开发机器或重新格式化它,我所需要做的就是简单地重新安装 Docker 就可以从我离开的地方继续。
总结…
如果您是一家初创公司,尚未决定如何为您的新技术堆栈提供支持,或者是一家成熟的服务提供商,正在考虑将您的生产和非生产环境容器化,但又害怕在“未经测试”的水域航行(笑),请考虑以下几点。
一致性
你可能拥有整个行业最优秀的开发人员,但由于市面上操作系统千差万别,每个人都倾向于使用自己的系统。如果你的本地环境已经正确配置了 Docker,那么新开发人员只需安装它,创建一个包含应用程序的容器,然后启动即可。
调试
您可以轻松地在整个团队中隔离和消除环境问题,而无需了解他们的机器设置。一个很好的例子是,我们曾经需要通过从 ntpd 迁移到 Chrony 来修复服务器上的一些时间同步问题——我们所做的只是更新了基础镜像,而我们的开发人员对此一无所知。
自动化
大多数 CI/CD 工具(包括 Jenkins、CircleCI、TravisCI 等)现在都与 Docker 完全集成,这使得将您的更改从一个环境传播到另一个环境变得轻而易举。
云支持
容器需要被监控和控制,否则你将不知道你的服务器上运行着什么,而云监控公司 DataDog 对 Docker 是这样说的:
容器的生命周期短且密度高,对基础设施监控有着重大影响。这意味着需要单独监控的事物数量将呈数量级增长。
解决这一艰巨任务的方法包括自管理云编排工具(例如Docker Swarm和Kubernetes)以及供应商管理工具(例如 AWS 的Elastic Container Service和Google Kubernetes Engine),它们用于监控和管理容器集群和调度。
随着 Docker 的广泛使用及其与 AWS 和 Google Cloud 等云服务提供商的紧密集成,将新应用程序或现有应用程序进行 Docker 化很快就会变得轻而易举。
鏂囩珷鏉ユ簮锛�https://dev.to/damianperera/why-docker-ggd