(翻译)与.NET容器映像保持同步

原文:https://blogs.msdn.microsoft.com/dotnet/2018/06/18/staying-up-to-date-with-net-container-images/

 

这篇文章描述了我们为你提供的生产和更新的容器镜像,你可以在 Docker ,Kubernetes 和其他系统中使用。当你一起用 .NET 和 Docker 镜像的时候,你可能正在使用微软官方的 .NET 容器镜像。过去一年我们对 .NET 镜像做了很多改进来使你更容易封装 .NET 应用。

 

在上周的 DockerCon 2018 期间,我发部了关于同时使用 .NET 和 Docker 的更新。它展示了如何使用 Docker 和 .NET 进行生产、开发和测试。这些场景都是基于 Docker Hub 上的 .NET 容器镜像。

更快的软件交付

Docker 是获取和使用 .NET 更新的游戏转换器。回想几年前。你可以下载最新的 .NET Framework 作为 Windows MSI 安装包,直到我们运行下一版本都不需要重新下载。快进到今天。我们一个月推送多次更新的容器镜像到 Docker Hub。每次你拉取 .NET 镜像,你就获得了更新的软件,一个 .NET 和/或底层操作系统的更新,无论是 Windows 还是 Linux。

这种新的软件交付模式更快并且在软件生产者和消费者之间建立了更强的联系。它也给你更多的控制,但在如何通过 Docker 获取软件上需要多一点的知识。重要的是要了解软件供应商的 Docker 仓库(repos)和标记(tags)——这个例子的 Microsoft——这样你就可以得到你想要的确切版本和更新。这篇文章旨在提供你需要的信息以便选择你需要的 .NET 镜像的最佳版本。

来自 Docker 的官方镜像

Docker 维护操作系统和应用平台的官方镜像。这些镜像是由 Docker 、熟练的社区开发者和指定技术(像 Alpine)的操作系统或应用平台维护人员一起来维护的。

官方镜像:

  • 正确和最佳的配置
  • 定期维护
  • 可以与其它应用程序共享(在内存里)

.NET 镜像是使用官方镜像构建的。我们在 AlpineDebianUbuntu 的 x64 和 ARM 的官方镜像上构建。通过使用官方镜像,我们将定期更新操作系统基础镜像和包(例如 OpenSSL)的成本和复杂性留给最接近这些技术的开发人员。相反,我们的构建系统配置了自动构建、测试和推送 .NET 镜像,无论在我们使用和更新官方镜像。使用这种方法,我们能以低成本在多个 Linux 发行版上提供 .NET Core 并在几小时内发部更新。还可以节省内存。.NET ,Java 和 Node.js 应用程序的组合在最同一台主机上,例如最新的官方 Debian 镜像,将在内存中共享 Debian 基础镜像。

来自 Microsoft 的 .NET 镜像

 .NET 镜像不是 Docker 官方镜像的一部分,因为他们仅由 Microsoft 维护。我们也在上面构建 Windows Server 镜像是相同的,类似于 Docker 官方镜像,我们有一个熟练于 .NET 和 Docker 的 .NET 镜像。这样的结果就是于上面描述的 Docker 官方镜像相同的好处。

我们用下列模型维护 .NET 镜像:

  • 发布新 .NET 版本或者基础操作系统镜像时推送同一天的镜像更新。
  • 在 VSTS CI系统成功验证后推送镜像到 Docker Hub。
  • 生成于 Visual Studio 中可用的 .NET 版本相匹配的镜像。
  • 使预览版软件可用于早期反馈并用在 microsoft/dotnet-nightly 上。

我们依靠 Docker 官方维护者及时地生成高质量的镜像以便我们的镜像重视最新的。我们知道你依赖我们为 .NET 做同样的事情。我们也知道当新的 .NET 镜像可用时,许多人会自动重构建镜像和包含的应用程序。非常重要的是这个过程运行良好,使你的应用程序总是运行在最新的 .NET 补丁版本和你选择使用的软件栈的其余部分上。这是我们一起工作的一部分以确保 .NET 应用程序在生产中安全可靠的。

 .NET Docker Hub 仓库

 Docker Hub 是一个伟大的服务,存储世界上的公共容器镜像。当我们第一次推送镜像到 Docker Hub时,我们创建了细粒度的存储库。许多细粒度的回购都有它的优点,但可发现性不是其中之一。我们听到了很难找到 .NET 镜像的反馈。为了帮助这一点,我们减少了我们使用的仓库数量。当前的 .NET Docker Hub 仓库如下:

.NET Core 仓库:

.NET Framework 仓库:

废弃仓库:

.NET 镜像标签

在 Dockerfile 文件中使用的镜像标记可能时各种 Docker-relaterd 资产中最重要的工件。标签定义了在运行 docker 构建预期要使用的底层软件和应用程序将在生产中运行的。标签让你对你拉取的镜像有很多控制,但是如果你使用的标签不符合你的需要,它也可能是痛苦的来源。

标签有四种主要的选择,从一般到最具体:

  • 最新版本 —— 最新标签与存储库中可用的软件的默认版本(无论存储库维护者认为默认的时什么,可能是或可能不是真正的最新版本)。当你没有制定标签时,你的请求会拉去最新的标签。从一个拉到下一个,你可能会获得软件和/或主要版本更新的底层操作系统。例如,当我们运载 .NET Core 2.0 时,最新标签(用于 Linux)从 .NET Core 1.1 跳到 2.0 同时 Debian 从 8 跳到 9。最新版是为了更好的实验,单对于其他任何事情都不是一个好的选择。你不希望你的应用程序在自动构建中使用最新版本。
  • 主要版本 —— 一个次要标签,如 2.0-runtime 或 2.1-skd,将你锁定在特定的软件更新系列中。这些示例标签将各自只接收 .NET Core 2.0 或者 .NET 2.1 更新。当你用 docker 构建时,你可以期望获得软件和底层操作系统的补丁更新。大多数情况下我们推荐这种形式的标签。它平衡了易用性和更新风险之间的竞争关系。例如,4.7.2-sdk .NET Framework 标签匹配这个标签样式。
  • 补丁版本 —— 主要版本.次要版本.补丁版本 标签,例如 2.0.7-runtime 锁定你到一个特定补丁版本的软件。从可预测性的角度来看,这是很好的。但是每次更新到一个新的补丁版本时都需要更新 Dockerfile。如果需要为多个应用程序部署 .NET 安全更新,则需要大量的工作。例如 4.7.2-sdk-20180523-windowsservercore-1803 .NET Framework 标签与次标签风格匹配。我们不更新补丁版本镜像中的 .NET 内容,但是我们可能会因为基础镜像的变化而为标签推出新镜像。因此,不要认为补丁版本标签是一成不变的。
  • 摘要 —— 你可以直接引用一个镜像摘要。这种方法给了你最大的可预测性。标签可以被新镜像覆盖但摘要不能。标签也可以删除。我们建议在应用程序由于镜像更新而中断时使用摘要,并且你需要返回到最新已知的好使的版本。确定一个不再使用的镜像的摘要可能时具有挑战性的。可以将日志添加到镜像构建基础设施中,以手机次信息作为意外损坏的保险策略。

标签是你想要的 .NET 版本上的一个合同。每次我们运行时都尽力满足合同。我们做两个主要的事情来产生有质量的容器镜像:CI 验证和代码审查。CI 验证在几个操作系统上运行,每次拉取请都请求到 .NET 仓库。这一级别的预先验证为我们提供了对推送到 Docker Hub 的 Docker 镜像的质量。

对于每个主要和次要 .NET 版本,我们可以采用一个新的主要操作系统版本依赖。正如前面提到的,我们采用 Debian 9 作为 .NET Core 2.0 的基础镜像。我们为 .NET Core 2.1 停留在 Debian 9。因为 Debian 10(又名 "Buster")还没有发部。Debian 9 仍然是 .NET Core 2.1 的默认基础镜像用于 .NET Core 2.1 的生命周期。一旦我们采用了底层操作系统的主要版本,我们就不会为给定的 .NET 版本的生命周期而改变它。

每个发行版都有自己的补丁模型。对于 .NET 补丁,我们将采用较小的 Debian 版本,例如(Debian 9.3-9.4)。如果你查看 .NET Core Dockerfiles,你可以看到各种 Linux 操作系统的依赖,如 DebianUbuntu。我们在我们支持的 Windows 和 Linux 操作系统的上下文和使用它们的社区中做出了有意义的决策。

Docker 的 Windows 版本控制与 Linux 不同,就像 multi-arch 标签的工作方式一样。简单的说,当你在 Windows 上拉取一个 .NET Core 或者 .NET Framework 镜像时,如果你使用 multi-arch 标签,我们将得到一个与主机 Windows 版本匹配的镜像(稍后会有更多关于这个的介绍)。如果需要不同的版本,则需要使用 Windows 版本的特定标签。一些 Azure 服务,像 Azure Container Instances(ACI) 只支持 Windows Server 2016(在编写时)。如果你的目标是 ACI,则需要使用 Windows Server 2016 标签,例如 4.7.2-runtime-windowsservercore-ltsc2016 或者 2.1-aspnetcore-runtime-nanoserver-sac2016,分别是为了 .NET Framework 和 ASP.NET Core。

.NET Core 标签方案

在 microsoft/dotnet 仓库中有多种镜像:

  • sdk —— .NET Core SDK 镜像,包括 .NET Core CLI,.NET Core 运行时和 ASP.NET Core。
  • aspnetcore-runtime —— ASP.NET Core 镜像,包括 .NET Core 运行时和 ASP.NET Core。
  • runtime —— .NET Core 运行时镜像,包括 .NET Core 运行时。
  • runtime-deps —— .NET Core 运行时依赖镜像,只包括 .NET Core 的依赖和 .NET Core 自己。这个镜像用于自包含的应用程序并只提供给 Linux。对于 Windows,你可以直接将操作系统基础镜像用于自包含的应用程序,因为它满足所有 .NET Core 依赖。

我们为下面操作系统做了 Docker 镜像:

  • Windows Nano Server 2016+
  • Debian 8+
  • Alpine 3.7
  • Ubuntu 18.04

.NET Core 支持多个芯片:

  • X64
  • ARM32v7

注意:ARM64v8 镜像将在稍后时间提供,可能随着 .NET Core 3.0。

.NET Core 标签遵循一个方案,它描述了 .NET Core 支持的各种镜像,操作系统和芯片的不同组合。

[version]-[kind]-[os]-[chip]

注意:这个方案是伴随 .NET Core 2.1 的新方案,早期版本使用类似但稍有不同的方案。
下面 .NET Core 2.1 标签是这个方案的例子:

  • 2.1.300-sdk-alpine3.6
  • 2.1.0-aspnetcore-runtime-stretch-slim
  • 2.1.0-runtime-nanoserver-1803
  • 2.1.0-runtime-deps-bionic-arm32v7

注意:你可能注意到这些标签中有一些使用了奇怪的名字。“bionic” 和 “stretch” 分别是 Ubuntu 18.04 和 Debian 9 的版本名称。它们分别是 ubuntu 和 debian 仓库的标签名称。“stretch-slim” 是 “stretch” 的小变种。当他们可用时我们使用更小的镜像。“nanoser-1803” 代表了 Windows Nano Server 的 Spring 2018 更新。“arm32v7” 描述了一个 32 位的 ARM 基础镜像。ARMv7 是由 ARM 控股公司定义的 32 位指令集。

它们也是 .NET Core 标签的短格式。短格式有两种不同的方式。他们使用两部分版本号并跳过操作系统。在大多数情况下,短格式标签是你想要使用的标签,因为他们更简单、更容易维护并且是 multi-arch 的,因此可以跨操作系统移植。

我们建议你在 Dockerfile 中使用以下 .NET Core 的短格式标签:

  • 2.1-sdk
  • 2.1-aspnetcore-runtime
  • 2.1-runtime
  • 2.1-runtime-deps

如上所述,一些 Azure 服务只支持 Windows Server 2016(而不是 Windows Server 1709 以上版本)。如果你使用其中之一,你可能无法使用短标签,除非恰好在 Windows Server 2016 上构建镜像。

.NET Framework 标签方案

在 microsoft/dotnet-framework 仓库中有多种镜像:

  • sdk —— .NET Framework SDK 镜像,包括 .NET Framework 运行时和 SDK。
  • runtime —— .NET Framework 运行时镜像,包括 .NET Framework 运行时。

 我们为下面 Windows Server 版本做了 Docker 镜像:

  •  Windows Server Core,version 1803
  •  Windows Server Core,version 1709
  •  Windows Server Core 2016

.NET Framework 标签遵循一种方案,它描述了各种镜像的不同组合以及 .NET Framework 支持的 Windows Server 版本:

[version]-[kind]-[timestamp]-[os]

 .NET Framework 版本号不使用 主版本.次版本.补丁版本 方案。版本号的第三部分不代表补丁版本。因此,我们在标签中添加了一个时间戳来创建唯一的标签名。

下面 .NET Framework 标签是这个方案的例子:

  • 4.7.2-sdk-20180615-windowsservercore-1803
  • 4.7.2-runtime-20180615-windowsservercore-1709
  • 3.5-sdk-20180615-windowsservercore-ltsc2016

它们也有 .NET Framework 标签的短格式。短格式有两种不同的方式。它们省略时间戳和省略 Windows Server 版本。在大多数情况下,这些都是你希望使用的标签,因为它们更简单、易维护并且是 multi-arch 的。因此可以跨 Windows 版本移植。

我们建议你在 Dockerfile 里使用以下短格式的标记,例如 .NET Framework 4.7.2 和 3.5:

  • 4.7.2-sdk
  • 4.7.2-runtime
  • 3.5-sdk
  • 3.5-runtime

正如上面所讨论的,一些 Azure 服务只支持 Windows Server 2016(不是 Windows Server 1709 以上版本)。如果使用其中之一,则可能无法使用短标记,除非你碰巧只在 Windows Server 2016 上构建镜像。

microsoft/aspnet 和 microsoft/wcf 使用这种标签方案的变种,并且将来可能会移到这个方案。

安全更新和漏洞扫描

由于你可能已经了解到这一点,所以我们定期更新 .NET 镜像,以便你可以使用最新的 .NET 和操作系统补丁。对于 Windows,我们的镜像更新本质上类似于 Windows 团队在 Windows 更新上提供的常规“星期二补丁”版本。事实上,我们通过最新的 Windows 补丁更新我们的 Windows 基础镜像在每个星期二补丁。你不能在容器中运行 Windows 更新。你可以通过 Docker Hub 上的最新的容器镜像重新构建。

在 Linux 上的更新体验更加微妙。我们支持多个 Linux 发行版本,可以随时更新。没有具体的时间表。此外,通常有一组发部的漏洞(AKA CVEs)是未修补的,其中没有可用的修复。这种情况并不特别适用在容器中使用 Linux,但通常使用 Linux。

有客户问我们为什么 .NET Core Debian 的基础镜像无法进行漏洞扫描。我使用 anchore.io 进行扫描,并验证了客户与我们共享的同样的扫描。漏洞来自我们使用的基础镜像。

你可以查看我查看的相同扫描:

我的一个观察结果是,Debian 和 Ubuntu 的扫描结果随着时间的推移而显著改变。对于 Alpine,它们保持稳定,报告的漏洞很少。

我们采用三种方法来部分缓解挑战:

  • 在最新的 Linux 发现版补丁更新时立即重新构建和发部 .NET 镜像(在几小时内)。
  • 一旦可用,支持最新版的主要版本。我们已经观察到最新的 distros 经常被修补的更快。
  • 支持 Alpine,这是更小的,所以有更少的组件会有漏洞。

这三种方法给了你很多选择。我们建议你使用 .NET Core 镜像,使用你选择的 Linux 发行版的最新版本。如果你更关心 Linux 上的漏洞,请使用 .NET Core 2.1 Alpine 镜像的最新补丁版本。如果你仍然不满意这种情况,那么考虑使用我们的 Nano Server 镜像。

使用预发行镜像

我们保持一个预发布 Docker Hub 仓库,dotnet-nightly。在 .NET Core 2.1 发布之前夜间构建的 .NET Core 2.1 镜像在那个仓库中可用。目前该仓库中有夜间构建的 .NET Core 1.x 和 2.x 服务分支。不久之后,你将看到可以测试夜间构建的 .NET Core 2.2 和 3.0。

我们也提供 .NET Core 和 Linux distros 的预发布版本。在它发布前我们提供 Ubuntu 18.04(又名 “bionic”)。我们目前提供 .NET Core 镜像与 Debian 10(又名 “buster”)的预发布版本和 Alpine edge 分支。

结束语

我们希望使你能够轻松直观的使用我们为 Windows 和 Linux 生成的官方 .NET 镜像。Docker 提供了一个伟大的软件交付系统使它很容易保持最新。我们希望你现在拥有了配置 Dockerfile 和构建系统所需的信息,以便使用为你的环境提供服务特性和镜像一致性的标签样式。

当我们收到反馈和 Docker 特性发生改变时,我们将继续对 .NET 容器镜像进行更改。我们在 dotnet/announcements 定期更新。“watch” 这个仓库以跟上最新的更新。

如果你是个 Docker 新手,请使用 .NET 和 Docker 一起检查。它解释了如何使用 Docker 在各种场景中使用 .NET。我们也为 .NET Core 和 .NET Framework 提供了义域使用和学习的示例。

在评论中告诉我们你如何一起使用 .NET 和 Docker。我们很想知道你使用 .NET 和容器的方式以及你希望看到的改进。

 

posted @ 2018-08-23 23:47  Blue-G  阅读(359)  评论(0编辑  收藏  举报