1.容器提供标准化开发
当解决方案提供商专注于提供价值而不是目标环境的复杂性时,每个人都会赢。这就是容器大放异 彩的地方。
随着容器技术产品(如 Docker)的广泛采用和标准容器运行时平台(如 Kubernetes)的持续普及 ,开发人员需要考虑的兼容性问题越来越少。虽然熟悉目标环境仍然很重要,但只要我们在开发过程中可以使用相同的平台,具体的操作系统、安装的实用程序和服务就不是那么重要了。我们认为这是越来越多的新容器运行时选项的原因之一。
对于针对本地环境的工作负载,可以根据所需的编排级别选择运行时平台。一些团队决定通过Docker-Compose 运行他们的少数服务,这对于开发和测试环境来说是典型的,对于生产安装来说并非闻所未闻。对于需要成熟的容器编排器的用例,Kubernetes(以及 OpenShift 等衍生产品)仍然占主导地位。
那些为云开发的人可以从众多选项中进行选择。Kubernetes 存在于所有主要的云平台中,但也有针对那些具有整体工作负载的选项,从半托管服务到完全托管服务,以获取那些简单的 Web 应用程序(如 Azure App Services 或 Google Cloud Platform 的 App Engine)。
对于那些冒险进入无服务器的人来说,部署单元通常是容器镜像或源代码,然后平台变成容器。
通过所有这些选项,关注我们的客户如何采用容器技术是一件很有趣的事情。较小公司的 IT 战略似乎对使用像我们这样的解决方案提供商反应更快。
但更大的公司也在迎头赶上。我们欢迎企业客户认识到使用容器和其他云原生技术构建和交付软件的好处的趋势。
总的来说,我们可以说作为集装箱的运输解决方案正在成为常态。我们在 Adnovum 使用 Docker,
我们已经看到了对开发人员的具体好处。让我们更多地看看这些好处。
2. 有限的曝光意味着更多的安全
针对容器平台(与传统操作系统包相对)也会带来安全后果。例如,假设我们有一个完全托管的 Kubernetes 平台。这意味着客户的 IT 团队负责以安全的方式配置和操作集群。在这些情况下,我们的开发人员可以将注意力集中在我们交付的应用程序上。得益于容器技术,我们可以进一步限制对各种攻击和漏洞的暴露。
这与容器的基本理念相关:通过仅打包应用程序绝对必要的内容,您还可以减少可能的攻击面。这可以通过从头构建镜像或选择安全基础镜像来封装您的可交付成果来实现。在Docker Hub上选择安全基础镜像时,我们建议过滤由经过验证的各方生成的容器镜像:
也有完整的打包过程由您的开发工具处理的情况。我们在许多 Web 应用程序项目中使用 Spring Boot。Spring Boot 包含buildpacks,它可以以高效可靠的方式从您的 Web 应用程序构建 Docker OCI 映像。这减轻了开发人员寻找基本图像的负担,并减少了(但并未完全消除)进行各种优化的需要。
3. 容器支持多样化的开发者环境
虽然 Adnovum 专门从事网络和移动应用程序开发,但在这些范围内,我们利用了广泛的技术。支持此类异构环境可能很棘手。
想象一下,我们有一个在 Linux 上工作的 spring boot 开发人员,另一个在 Mac 上开发 Angular 前端。他们都依赖一组工具和依赖项在他们的机器上开发项目:
本地数据库实例
第三方服务的测试替身(模拟等)
浏览器——有时有多个版本
开发人员工具,包括运行时和构建工具
根据我们的经验,如果这些工具是本机安装的,则很难跨多个操作系统支持这些工具。相反,我们尝试将尽可能多的这些推送到容器中。这有助于我们调整开发人员的体验并降低跨平台的维护成本。
我们在 Windows 或 Mac 上工作的开发人员可以使用Docker Desktop,这不仅允许他们运行容器,还带来了一些额外的功能(Docker Desktop 在 Linux 上也可用,或者您可以选择直接使用 docker-engine)。例如,我们可以开箱即用地使用docker-compose,这意味着我们无需担心确保人们可以在各种操作系统上安装它。在许多此类工具上执行此操作可以为您的支持团队显着降低认知和成本。
如果您的开发人员需要同时跨多个项目工作,以这种方式外包您的依赖项也很有用。毕竟,没有人喜欢安装多个版本的数据库、浏览器和工具。
我们通常可以将此技术应用于我们最近的项目,而对于技术早于 Docker 大规模采用的旧项目,我们仍有功课要做。
4. 容器有助于再现性
作为专业的软件制造商,我们希望确保我们不仅为客户提供出色的解决方案,而且如果有任何问题(功能或安全性),我们可以将问题追溯到产生工件的确切代码更改——通常Web 应用程序的容器映像。最终,我们可能还需要重建所述工件的固定版本,这被证明是具有挑战性的。这是因为构建环境也会随着时间的推移而发展,不断改变它们提供的兼容性窗口。
根据我们的经验,自动化(特别是基础架构即代码)是为开发人员提供可靠且可扩展的构建基础架构的关键。我们希望能够在软件或硬件出现故障时迅速重建环境,或者根据旧的配置参数提供基础设施组件以进行调查。我们的策略是通过 Ansible 或 Terraform 等工具管理所有基础设施,我们强烈建议工程师避免手动管理服务。我们的数据中心和云环境也是如此。
只要有可能,我们也更喜欢将服务作为容器运行,而不是将它们安装为传统的包。您会在Docker Hub上找到许多流行的基础设施服务,例如NGINX和PostgreSQL。
我们尝试推动密封构建,因为它们可以引导自己的依赖项,这大大减少了它们对特定 CI/CD 平台提供的构建上下文中安装的内容的依赖。从历史上看,我们在支持依赖于机器上安装的浏览器的自动化 UI 测试方面遇到了挑战。随着我们项目数量的增加,他们对浏览器版本的期望也有所不同。即使我们致力于自动化,这很快就变得难以支持。后来,我们在使用 Node.js 和 Java JDK 等工具时遇到了类似的挑战,几乎无法满足需求。
最终,我们决定在我们的自动化构建中采用引导和容器,允许团队定义他们的项目需要的 Chrome 或 Java 版本。在 CI/CD 管道期间,将在构建之前下载所需的版本依赖项,以防它尚未缓存。
不变性意味着我们的依赖关系和我们的产品,就此而言,在构建之后永远不会改变。不幸的是,这并不是 Docker 标签的工作方式。事实上,Docker 标签在设计上是可变的,如果您习惯了SemVer ,一开始可能会感到困惑。
合乎逻辑的假设是,每当您(重新)构建自己的图像时,都会使用相同的基础图像。实际上,标签可以指向不同的图像,以防有人决定在同一标签下发布新图像。他们这样做可能出于多种原因:有时是出于必要,但也可能是出于恶意。
如果您想确保您将使用与以前完全相同的图像,您可以开始通过它们的摘要来引用图像。这同时是可用性和安全性的权衡。虽然使用摘要使您更接近真正可重现的构建,但这也意味着如果基础镜像的作者在同一标签下发布新的镜像版本,那么您的构建将不会使用最新版本。无论您倾向于哪一方,您都应该使用来自可信来源的基础图像,并将漏洞扫描引入您的管道。
结合不变性(及其所有挑战)、自动化和密封构建,我们将能够重建我们代码的旧版本。您可能需要这样做来重现错误——或者在发布修复的工件之前解决漏洞。
虽然我们仍然看到自己在实现可重复性的过程中有改进的机会,但在此过程中使用容器是我们将再次做出的决定。