本文讲的是.NET 和 Docker结合使用【编者的话】本文主要围绕 .NET 和 Docker 结合的几个方面,.NET 团队所提供的包括基础入门,使用场景等实践,以及他们在推进 .NET 和 Docker 结合上所做出的努力,同时也提供了一些示例文件和经验,可以帮助用户更加容易地使用和迁移现有服务。
【3 天烧脑式 Docker 训练营 | 上海站】随着Docker技术被越来越多的人所认可,其应用的范围也越来越广泛。本次培训我们理论结合实践,从Docker应该场景、持续部署与交付、如何提升测试效率、存储、网络、监控、安全等角度进行。
许多与我交流的开发者要么在积极地使用 Docker,要么计划在他们的环境中采用容器技术。容器是我们这个行业的一个重要趋势,.NET 是其中的一部分。 Microsoft 和 Docker 一直在合作,以便在开发 .NET 应用时,使用 Docker 可以有一个良好的体验。
Docker生态系统 始于 Linux 技术。你可以在 Linux 和 .NET Core 上使用同其他开发平台一样的 Docker 工作流。.NET 团队经常会在 Docker Hub 的 microsoft/dotnet 仓库中更新 Debian 镜像。
Windows 团队最近发布了 Windows Server 2016,并更新了 Windows 10,而且在 Windows 上支持了容器。现在 .NET Core和 .NET Framework 都可以与 Windows 容器结合使用。
上述支持在使用 Docker 构建和打包 .NET 应用的方式上提供了很多选择。这篇文章介绍了其中的一些选择,并提供了入门信息,即使你是个 Docker 新手也没关系。
想象一下,五年前如果有人在面试中告诉你,他们非常关心一致性,所以需要经常与应用一起部署操作系统。当时你可能不会雇佣他们。然而,这正是目前 Docker 的典型应用场景!
例如,如果需要为 .NET 团队添加容器的测试用例。我们会将基础设施的重要部分转移到容器上,以便从容器的优势中受益,而不是简单地“在 Docker 容器中测试 .NET”。这种方法为我们提供了双重优势:在容器中运行 .NET 的高度信心以及更加高效的整体流程和更低的成本。 在这个案例中,我们每年为基础设施实验室节省了一个人力的时间成本和每年10万美元的云服务机器成本。我很高兴我们能够节省这些费用。
如果你是 Docker 新手,建议你在 Docker 文档中查看 Docker 入门 部分,我也是从那入门的。该说明使用 Linux 容器,但如果你不是 Linux 用户,也不用担心,你可以找到与你使用的操作系统对应的 Docker 客户端使用说明,以及针对通用 Docker 概念和机制的指南。
接下来,可以尝试使用我们提供的 .NET 与 Docker 结合使用的示例。 这些示例应该可以帮助你开始使用 .NET 和 Docker。 我们创建了两组样本,因为 .NET Core 和 .NET Framework 之间的关键不同在于需要不同 Dockerfile 和其他组件。
我们 push 了一些镜像到 Docker hub,以便大家可以更加容易地使用它们:
通过使用示例镜像,你可以在机器上尝试 .NET,而无需安装任何东西( Docker 除外)。也就是说,我认为在本地环境中尝试示例仍然是充分体验和评估 .NET 与 Docker 的最佳实践。
例如,针对 .NET Core,可以尝试以下 Linux 镜像(如果使用Docker for Windows,请务必切换到 Linux 容器):
我们将 Docker 镜像发布在 Docker Hub 上几个不同的仓库中。 镜像分割很重要,这样可以在 Docker Hub 以及
我们也在 Docker Hub 上发布了示例,以便大家可以更加容易地使用。
基础镜像的使用说明及示例可以参照上述提供的 Docker Hub 链接。 如果你刚刚接触 Docker 分层概念,我们建议你阅读 Docker 关于 理解镜像、容器和存储驱动 的文档。
这些文件定义镜像内容和其他特征。在多数情况下,我们会研究其他平台对镜像的处理,并尝试遵循行业规范。也有一些情况下,我们会选择做一些最适用 .NET 应用程序的工作,这些工作可能会也可能不会适用于其他平台。 通常情况下,Docker 员工为其他平台创建初始化镜像,所以我们在 Docker Hub 上看到的自由“复制”模式实际上只是在追随 Docker。随着 Docker 规范的变化,我们将尽最大努力地将这些变化应用在 .NET 镜像上。
Dockerfile 源文件存储在 GitHub 上。 你可以关注我们关于镜像的进展。如果你愿意的话,也可以看看我们制作镜像的原因并参与讨论。
在 Docker Hub 上,仓库名称为镜像的名称,标签通过版本号或其他标志来消除仓库中镜像的歧义。
dotnet 仓库的一个重要选项是打上
替代方案是将
我们最近做出了一些改变 .NET Core Docker 镜像使用连拱 (multi-arch) 标签 。 此改变可以让你减少对上述第三个维度的考量。这意味着你的 Dockerfile 文件不再需要定义要使用的操作系统。
对于 Windows 镜像, 在 .NET 的 Dockerfile 定义中依赖了一个特定的基础镜像,具体可以参考 microsoft/dotnet:1.0-runtime-nanoserver Dockerfile 中的第一行,如下:
在“补丁周二”(每个月的第二个星期二),Windows团队通常会发布补丁并更新其基础图像,.NET 镜像也会更新。
对于 Linux 镜像,.NET Dockerfile 中定义依赖了一个更通用的基础镜像,该镜会随时间发生变化。目前,.NET Core 选用
Debian 仓库包括 Debian Stretch(Debian 9)的镜像,这是Debian Jessie(Debian 8)之后的一个版本。我们不会将使用 Debian Jessie 的 .NET Core 标签自动前滚到 Debian Stretch,但会像其他平台一样,为其创建一个新标签。
在 DockerCon 2017 上,一款名为 Image2Docker 的工具着实令人兴奋,它可以将 Windows VM 迁移到容器。该工具由 Docker 在 GitHub 上维护。
Image2Docker 的 PowerShell 模块可与 VHD,VHDX 或 WIM 镜像文件一起使用,并生成可构建 Docker 镜像的高保真 Dockerfile。该工具可以帮助你构建一个与 VHD 相同的 Docker 镜像,同时还能发挥 Docker 的优势。Image2Docker 虽然不会构建出最漂亮的 Dockerfile,但对于希望将 .NET Framework 应用迁移到容器的用户来说,这是一个不错的开始!
更多信息可参考 DockerCon 演讲之 Image2Docker , 或者阅读 Docker 官方文章: 使用 Image2Docker 将 ASP.NET 服务转换为 Docker
注: 运行 Image2Docker 需要安装 Windows版本的 Docker。
在此,我想为在 Docker 工作的同事点赞。我们一直在与他们其中的很多同事合作,致力于 .NET 和 Docker 更好地结合。当我们提出可以让 .NET 开发人员更友好的改进时,Docker 的同事也很乐意接受建议。连拱标签和多级构建是我们早期参与而获益的一个良好示例。
【3 天烧脑式 Docker 训练营 | 上海站】随着Docker技术被越来越多的人所认可,其应用的范围也越来越广泛。本次培训我们理论结合实践,从Docker应该场景、持续部署与交付、如何提升测试效率、存储、网络、监控、安全等角度进行。
许多与我交流的开发者要么在积极地使用 Docker,要么计划在他们的环境中采用容器技术。容器是我们这个行业的一个重要趋势,.NET 是其中的一部分。 Microsoft 和 Docker 一直在合作,以便在开发 .NET 应用时,使用 Docker 可以有一个良好的体验。
Docker生态系统 始于 Linux 技术。你可以在 Linux 和 .NET Core 上使用同其他开发平台一样的 Docker 工作流。.NET 团队经常会在 Docker Hub 的 microsoft/dotnet 仓库中更新 Debian 镜像。
Windows 团队最近发布了 Windows Server 2016,并更新了 Windows 10,而且在 Windows 上支持了容器。现在 .NET Core和 .NET Framework 都可以与 Windows 容器结合使用。
上述支持在使用 Docker 构建和打包 .NET 应用的方式上提供了很多选择。这篇文章介绍了其中的一些选择,并提供了入门信息,即使你是个 Docker 新手也没关系。
为什么选择容器?
下面列出了开发人员 迁移到容器 的关键原因:- 一致性:容器包括应用程序及其所有依赖项。不管是在计算机、本地环境或是云端,应用程序都执行相同的代码。
- 轻量级:通过使用基于主机操作系统的最小量级抽象,并在容器之间共享公共资源,容器可以快速启动并使用最少量的 RAM。
- 共享性:容器镜像可以通过 Docker Hub、Docker Store 和私有 Docker 仓库(如 Azure 镜像仓库)轻松实现分享。
- 简单而强大:DockerFile 格式(容器镜像的 recipe)是一种可以实现强大场景的简单格式:优雅地将操作系统和容器的特定命令结合,并且还可以创建 Docker 镜像层。
想象一下,五年前如果有人在面试中告诉你,他们非常关心一致性,所以需要经常与应用一起部署操作系统。当时你可能不会雇佣他们。然而,这正是目前 Docker 的典型应用场景!
例如,如果需要为 .NET 团队添加容器的测试用例。我们会将基础设施的重要部分转移到容器上,以便从容器的优势中受益,而不是简单地“在 Docker 容器中测试 .NET”。这种方法为我们提供了双重优势:在容器中运行 .NET 的高度信心以及更加高效的整体流程和更低的成本。 在这个案例中,我们每年为基础设施实验室节省了一个人力的时间成本和每年10万美元的云服务机器成本。我很高兴我们能够节省这些费用。
Docker 在 .NET 应用中的使用场景
使用 Docker 和 .NET 应用程序的最典型场景是用于生产环境部署和托管。 事实证明,生产环境部署只是一种场景,而针对其他场景 Docker 同样有用。 这些场景虽然不是 .NET 特有的,但应同样适用于大多数开发平台。- 低摩擦安装——在机器上无需安装任何东西,只需下载一个预装 .NET 的 Docker 镜像,你就可以尝试使用 .NET。
- 在容器中开发——你可以在一致的环境中开发,开发环境和生产环境非常相似(这样可以避免一些诸如开发机中的全局状态等此类的问题)。Visual Studio Tools for Docker 甚至可以直接从 Visual Studio 中启动容器。
- 在容器中测试——你可以在容器中进行测试,减少由于环境配置错误或上次测试遗留的其他更改导致的失败。
- 在容器中构建——你可以在容器中构建代码,无需为多个环境正确配置共享的构建机器,而是转为 “BYOC”(自带容器)的方法。
- 在测试环境、staging 环境、生产环境以及其他环境中部署——你可以在所有环境部中部署同一个镜像,减少由于配置不同导致的失败。通常只通过外部配置(例如,注入的环境变量)来更改镜像的行为。
如何入门
现在可以在 Windows 、 MacOS 或 Linux 上使用 .NET 容器。 首先,你需要一个 Docker 客户端,最佳获取途径是 Docker.com 。 如果是在 Windows 平台上,请下载 Docker for Windows (稳定版本)。 Docker 同时支持 Windows 和 Linux 容器。 如果你是 Azure 用户,可以查看 Docker Edition for Azure 。如果你是 Docker 新手,建议你在 Docker 文档中查看 Docker 入门 部分,我也是从那入门的。该说明使用 Linux 容器,但如果你不是 Linux 用户,也不用担心,你可以找到与你使用的操作系统对应的 Docker 客户端使用说明,以及针对通用 Docker 概念和机制的指南。
接下来,可以尝试使用我们提供的 .NET 与 Docker 结合使用的示例。 这些示例应该可以帮助你开始使用 .NET 和 Docker。 我们创建了两组样本,因为 .NET Core 和 .NET Framework 之间的关键不同在于需要不同 Dockerfile 和其他组件。
我们 push 了一些镜像到 Docker hub,以便大家可以更加容易地使用它们:
通过使用示例镜像,你可以在机器上尝试 .NET,而无需安装任何东西( Docker 除外)。也就是说,我认为在本地环境中尝试示例仍然是充分体验和评估 .NET 与 Docker 的最佳实践。
例如,针对 .NET Core,可以尝试以下 Linux 镜像(如果使用Docker for Windows,请务必切换到 Linux 容器):
docker run microsoft/dotnet-samples
Docker Hub 中的 .NET
使用 .NET 与 Docker 的一个重要方面是要依赖 .NET 团队提供的 .NET 基础镜像。 为什么使用 .NET 基础镜像是一个好主意呢?至少有以下四个原因:- .NET 团队提供了基础镜像,所以你不必再造轮子。
- .NET 团队会定期更新镜像,其中包括一些针对安全性的更新。
- 当多个应用程序在同一台机器上使用相同镜像时,Docker 共享这些镜像的内存。镜像必须相同才能共享。
- Docker 会扫描镜像来发现安全漏洞,可以提供有关环境的更多信息。
我们将 Docker 镜像发布在 Docker Hub 上几个不同的仓库中。 镜像分割很重要,这样可以在 Docker Hub 以及
docker search
命令中更容易找到它们。
- microsoft/dotnet——适用于 Linux 和 Nano Server 的 .NET Core 运行时 和 SDK 镜像。
- microsoft/aspnetcore — 适用于 Linux 和 Nano Server 的ASP.NET Core 镜像。
- microsoft/aspnetcore-build——适用于 Linux 和 Nano Server 的 ASP.NET Core 镜像,用于构建应用程序。
- microsoft/dotnet-framework——适用于 Windows Server Core 的 .NET Framework 3.5 和 4.6.2 镜像。
- microsoft/aspnet——适用于 Windows Server Core 的 .NET Framework 3.5 和 4.6.2 ASP.NET 镜像。
我们也在 Docker Hub 上发布了示例,以便大家可以更加容易地使用。
- microsoft/dotnet-samples——.NET Core 示例。
- microsoft/dotnet-framework-samples——.NET Framework 示例。
基础镜像的使用说明及示例可以参照上述提供的 Docker Hub 链接。 如果你刚刚接触 Docker 分层概念,我们建议你阅读 Docker 关于 理解镜像、容器和存储驱动 的文档。
定义 Docker 镜像
Docker 镜像(包括 .NET 镜像)由一个相对简单的 Dockerfile 格式 文件定义。你可以在上述提供的 Docker Hub 仓库中找到每个镜像的 Dockerfile 文件的链接。这些文件定义镜像内容和其他特征。在多数情况下,我们会研究其他平台对镜像的处理,并尝试遵循行业规范。也有一些情况下,我们会选择做一些最适用 .NET 应用程序的工作,这些工作可能会也可能不会适用于其他平台。 通常情况下,Docker 员工为其他平台创建初始化镜像,所以我们在 Docker Hub 上看到的自由“复制”模式实际上只是在追随 Docker。随着 Docker 规范的变化,我们将尽最大努力地将这些变化应用在 .NET 镜像上。
Dockerfile 源文件存储在 GitHub 上。 你可以关注我们关于镜像的进展。如果你愿意的话,也可以看看我们制作镜像的原因并参与讨论。
Docker 镜像标签化
Docker 镜像具有隐藏 ID(例如,d99acb94e777),用于默认识别。 因为 ID 对用户来说并不是很有用,所以我们可以给 Docker 镜像打标签。标签通常是描述镜像用途的的友好名称,例如 “hello-world-app”。该机型在本地运行良好。在 Docker Hub 上,仓库名称为镜像的名称,标签通过版本号或其他标志来消除仓库中镜像的歧义。
.NET Core 标签
对于 .NET Core, 标签 用于描述以下三个维度的镜像差异:- .NET Core 版本——.NET Core 1.0, 1.1 and 2.0(撰写本文时)。
- .NET Core 分布——.NET Core 运行时,.NET Core SDK, .NET Core dependencies 依赖项。
- 操作系统基础镜像——Windows 和 Linux。
dotnet 仓库的一个重要选项是打上
latest
标签。我们决定
latest
标签总是指向最新的 .NET Core SDK 版本。例如,作为RTM时,
latest
将更新指向 .NET Core SDK 2.0。
替代方案是将
latest
映射到 .NET Core 运行时。我们认为,SDK是你起步的最佳镜像,一旦你体验了较大的 SDK,就可以更容易地做出优化的选择。
我们最近做出了一些改变 .NET Core Docker 镜像使用连拱 (multi-arch) 标签 。 此改变可以让你减少对上述第三个维度的考量。这意味着你的 Dockerfile 文件不再需要定义要使用的操作系统。
.NET Framework 标签
对于.NET Framework, 标签 仅在一个维度上描述镜像差异:- .NET Framework 版本 — 3.5, 4.6.2
latest
标签对应最新版本的 .NET Framework。当镜像可用时,
latest
将会更新并指向 4.7 版本。
仓库分割
关于如何构建仓库没有现成的硬性规定。下面这条是个不错的参考:
从仓库中执行
docker pull
拉取到的镜像,应当是一个意义明确的镜像,仓库中的其他镜像应当紧紧围绕与默认镜像相关的附加概念而存在。
仓库中的标签越多,其中某些镜像应当属于其他仓库的可能性越大。 这是我们正在讨论的东西,与 Docker 方面也在讨论这个问题。我们希望将 .NET Core 仓库分为两个或三个,这样便于用户使用。不幸的是,目前没有比较好的机制来找到其他相关联的库。我们希望这个问题可以得以解决,这样我们可以更加自由的分割仓库。
更新镜像
.NET 镜像经常更新,有时是 安全性更新 。可以通过执行docker pull
下载这些更新,
docker build
不会从服务器请求更新。
对于 Windows 镜像, 在 .NET 的 Dockerfile 定义中依赖了一个特定的基础镜像,具体可以参考 microsoft/dotnet:1.0-runtime-nanoserver Dockerfile 中的第一行,如下:
FROM microsoft/nanoserver:10.0.14393.1198
在“补丁周二”(每个月的第二个星期二),Windows团队通常会发布补丁并更新其基础图像,.NET 镜像也会更新。
对于 Linux 镜像,.NET Dockerfile 中定义依赖了一个更通用的基础镜像,该镜会随时间发生变化。目前,.NET Core 选用
Debian Jessie
,并向 Jessie 发布更新(例如8.6 到 8.7)。你可以在
microsoft / dotnet:1.0-runtime-deps Dockerfile
Dockerfile 定义的第一行看到,如下所示:
FROM debian:jessie
Debian 仓库包括 Debian Stretch(Debian 9)的镜像,这是Debian Jessie(Debian 8)之后的一个版本。我们不会将使用 Debian Jessie 的 .NET Core 标签自动前滚到 Debian Stretch,但会像其他平台一样,为其创建一个新标签。
迁移 .NET Framework 应用到容器
如果有工具可以将 VHD 转换为容器,岂不是让人很兴奋?在 DockerCon 2017 上,一款名为 Image2Docker 的工具着实令人兴奋,它可以将 Windows VM 迁移到容器。该工具由 Docker 在 GitHub 上维护。
Image2Docker 的 PowerShell 模块可与 VHD,VHDX 或 WIM 镜像文件一起使用,并生成可构建 Docker 镜像的高保真 Dockerfile。该工具可以帮助你构建一个与 VHD 相同的 Docker 镜像,同时还能发挥 Docker 的优势。Image2Docker 虽然不会构建出最漂亮的 Dockerfile,但对于希望将 .NET Framework 应用迁移到容器的用户来说,这是一个不错的开始!
更多信息可参考 DockerCon 演讲之 Image2Docker , 或者阅读 Docker 官方文章: 使用 Image2Docker 将 ASP.NET 服务转换为 Docker
注: 运行 Image2Docker 需要安装 Windows版本的 Docker。
结语
作为一个团队,我们至今已持续大约两年的时间专注于 .NET 与 Docker 的结合。期间,我们针对 Docker 的方案发生了很大变化,很大程度上是为了适应了 Docker 生态系统的快速变化。我们本身也大量使用 Docker。 我们将继续调整步伐来确保 .NET 是容器化应用程序的最佳平台之一。在此,我想为在 Docker 工作的同事点赞。我们一直在与他们其中的很多同事合作,致力于 .NET 和 Docker 更好地结合。当我们提出可以让 .NET 开发人员更友好的改进时,Docker 的同事也很乐意接受建议。连拱标签和多级构建是我们早期参与而获益的一个良好示例。
原文链接:Using .NET and Docker Together(翻译:李加庆)
原文发布时间为:2017-06-14
本文作者:李加庆
本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。
原文标题:.NET 和 Docker结合使用