在 Docker 上运行. NET Core

2,584 阅读10分钟
原文链接: dockone.io

【编者的话】本文为Jurgis Pasukonis在medium.com博客中发布的关于在Docker上运行.NET Core的文章,介绍了目前.NET Core在Docker上的开源情况及部分演示。Jurgis目前是TRAFI公司的CTO。

对于Microsoft和.NET来说,这是一个新的时代,然而这并不是言过其实的。如果你之前没有追随过这些消息,那么下面是一些发生在去年与此有关的事情:


把所有这一切放在一起,你会得到一个完整的体验,不论你是在Windows或者Mac上开发C#语言,你甚至可以在Windows上正确的使用基于类UNIX的命令行开发工具,并能够愉快地部署到Linux服务器上。基本上来说.NET/C#已经超越Java作为真正的跨平台开发生态系统。

计划

为了得到新玩具的这些体验,我已经提出了如下计划:
  1. 在MAC上通过.NET Core和C#创建一个“hello world”的网络服务。
  2. 在Docker上运行
  3. 部署到AWS容器服务上


来尽情地玩耍吧。

第一步:配置

.NET Core

我之所以决定在MAC OSX而不是在Windows上运行是为了让它更有意思(再加上运行Docker的时候会更简单)安装.NET是非常便捷的,我们只要照着以下步骤做。


.NET Core安装步骤
这给了你一个dotnet的命令行工具可以让你不用任何IDE来创建,构建,运行项目。接下来是告诉你如何创建并运行一个新的“Hello World”控制台应用程序:

Visual Studio Code

如果你喜欢纯文本编辑器,那么这就是你需要的。我喜欢漂亮的IDE体验,幸运地是Visual Studio Code编辑器可以运行在Windows,OSX和Linux上(不用将其与Visual Studio IDE混淆,这是只有Windows才能用的)。Visual Studio Code是一个轻量但功能强大的通用文本编辑器,拥有多种语言的插件支持,这其中也包括了C#。重申,它可以很轻松地从Visual Studio Code网站进行下载和安装:


Visual Studio Code download
然后你应该可以在启动之后添加C#的扩展(按F1然后输入“install extension”)。你最好读一下这样可以有更好的主意知道VS Code是如何工作的:


Visual Studio Code basics
一旦你在VS Code里打开.NET项目,你可以看到突出显示,自动完成的语句和调试!

这就是你去开发一个完全成熟的.NET项目需要的所有工具-在Windows,OSX和Linux上!

第二步:ASP.NET Core

我们的目标是要一个Web服务而不是一个控制台应用程序。对于.NET Core来说,额外有一个精巧的Web框架的ASP.NET Core(相比原来的ASP.NET已经完全重写了)。我们可以照着以下步骤将我们的测试应用程序转换成网页服务:


ASP.NET Core入门指南
  1. 对project.json添加 Microsoft.AspNetCore.Server.Kestrel依赖。
  2. 对Startup.cs类添加样本请求处理。
  3. 在Main()中启动网页服务器。
3.png

是的,在命令行中执行dotnet run或者在VS Code中用F5可以启动虚拟主机监听HTTP的请求。

5.png

考虑一下——不需要IIS,不需要Windows,不需要安装,你在10行代码中就获得了一个完整的独立的Web应用程序。

小插曲:NuGet/.NET Framework/.NET Core/.NET Standard,etc

到目前为止,我还没有真正解释什么是.NET Core以及它与通常的.NET框架的联系。当然这两者有很多的变化,而且经常会把他们弄混淆(不争的事实是一些工具和命名已经从Alpha到beta再到RC1甚至到RC2的版本中被改变了)。这里是官方的概述
  • .NET Core实际上是.NET Framework4.6的一个端口并且删除了所有Windows依赖关系而可以让其运行在Linux和OSX上。作为在GitHub上的一个开源项目来说,发展是积极的。这包括运行于不同平台和跨平台的标准库
  • .NET核心库包含完整的.NET框架的一个子集,并且有些部分还尚未移植,或者永远不会(例如System.Web和ASP.NET WebForms)。这意味着移植现有的项目并不完全微不足道,如果他们用的依赖关系并不在.NET Core中。这里是关于移植的一些信息
  • 一旦你简历一个新应用,你将会看到project.json文件替代了老的基于MSBuild的名为scproj的文件。它描述了依赖关系等等,然而,不同于scproj,它不会在项目中列出所有*.cs文件-这个所谓的项目是在该目录中的所有东西。
  • .NET Core使用NuGet管理所有的依赖,这其中包含了标准库,使得它可以完全模块化。例如,默认情况下projectson引用Microsoft.NETCore.App的NuGet依赖,这是在.NET Core中的所有标准库的包装。检查一下NuGet页面中的依赖列表-你会看见例如System.Net、System.Ling等等-所有这些都是NuGet的组件。
  • 其实有很多类似的“目标框架”可供你构建你的应用,包括 .NET Core (netcoreapp)、 .NET Framework(net)、Universal Windows Platform(uwp)、Mono Android(monoandroid)。这在project.json里已经做了指明(例如netcoreapp1.0),同时NuGet处理基于目标的依赖-可以在此检查关于任何新的NuGet组件的依赖清单-你会看到他们通过目标框架进行分组。
  • .NET 1.X标准目标框架是一套统一的对不同.NET目标框架所支持的功能。而新的NuGet包将尝试去定位这些,这意味着他们可以在任何兼容的框架中运行。这里是解释和关于不同的框架以及版本的详细信息
  • DNXCore5.0(dnxcore50)是.NET Core过时的名称,但是一些NuGet组件还在使用它,并且代码行{“import”:"dnxcore50"}在project.json说明了如果用到.NET Core的话会只使用该版本。
  • 如果你有一些第三方的NuGet依赖,像Json.NETDapperAzure SDK这些,并且也不知道他们会在.NET Core上运行--仅仅需要检查他们在NuGet页面上是否有.NET标准目标。大多数被积极开发的包刚刚发布(截至2016年5月)的测试版或RC版本的.NET目标标准/.NET Core。
  • ASP.NET Core是一个全新的Web框架,几乎与之前的ASP.NET没有相同的地方。这是理应更为简洁,速度更快,并可以让他运行在任何基于libuv自托管的Kestrel服务器上。这里可以查看一些文档


这是上手的一些基本信息,当然,还有更多的东西需要去学。

第三步:配置Docker

让我们试着在我们的Docker.Full上运行我们的.NET网页服务-在这之前,我从来没有在Mac上运行Docker。让我们通过安装Docker来开始:


在Mac OS X上安装Docker
如果进展顺利,可以运行docker run hello-world
7.png

接下来让我们返回.NET,这是一个官方的.NET Core的容器在DockerHub上,让我们运行它:

9.png

好了,我们已经获得了在Linux容器里运行.NET。

第四步:创建Docker镜像

接下来的步骤是将我们的.NET网络服务打包进一个Docker容器中(在Mac上创建的)。

首先,为了构建一个可部署的.NET程序包先来运行dotnet publish

这会将偶有依赖复制到发布路径,除了.NET Core框架本身。输出的结果将会包含testapp.dll文件,这将会通过执行donet testapp.dll产生。事实上,有一种方法来进行“本地”部署,其中包括了.NET框架和目标系统的二进制可执行文件,但我们在这里并没有这么做。

一旦app被建立了,我们会通过以下的Dockerfile将其打包进一个容器里
FROM microsoft/dotnet:latest
COPY bin/Debug/netcoreapp1.0/publish/ /root/
EXPOSE 5000/tcp
ENTRYPOINT dotnet /root/testapp.dll

这需要基础的 microsoft/dotnet镜像,复制publish的输出目录,公开其5000端口并执行.NET应用程序。

然后构建容器(docker build -t testapp .)并运行(docker run -it -p 5000:5000 testapp)

看起来他正常工作了!唯一出现的问题是该页面服务仅仅监听localhost:5000,所以它不响应来自外部的请求。我们需要通过调节Program.cs中的该*:5000选项作为监听地址
12.png

再一次运行( publish > docker build > docker run)进程
13.png

14.png

成功!

第五步:在AWS上运行

在这之前运行.NET服务的时候的一个烦恼是,你必须将他们部署为Windows服务的一些共享主机。这介绍了各种问题例如缺乏隔离,缺乏独立检测以及繁琐的部署脚本等。当在云端运行的时候,另一种可供选择的方案是为每个服务启动一台单独的虚拟机(VM),但这会造成资源的极度浪费(特别是当其运行在Windows宿主机上的时候)并额外的让部署时间加长。

容器服务似乎提供了一个完美的解决方案:你有主机集群,在那里你部署的每一个服务会作为一个单独的容器。当然,只有真正适用于Linux的,现在随着.NET Core开启了使用.NET这种策略的服务。

现在有多重容器服务的选项,但是由于我们TRAFI已经在Amazon Web Services(AWS)上运行所有应用,让我们来试试他们的Amazon EC2 Container Service(ECS)

我们照着ECS的入门指导步骤,这会帮助我们安装AWS命令行,创建AWS Docker仓库,并推送我们的本地镜像到AWS仓库中。

为了运行一个容器,你可以把它描述为Task Definition,这其中包括了端口映射以及资源限制(内存、CPU等等)。

并创建一个集群来托管容器。

一旦集群启动,我们可以运行一个新的容器任务将其放置到集群中:
18.png

它启动真的很快,而且我们已经得到了我们的在云端运行的Web服务!
19.png

这只是基本的用法,但是这时候你就已经有了正在运行的多个实例任务,并包含了负载均衡,自动重启失败实例,零停机时间部署等等这些状态。

此外,容器使得构建和部署流程非常友好和干净-人们可以有一个CI构建去创建并上传Docker容器,然后对于部署来说仅仅是一条单一的AWS CLI命令就使得其可以使用新的容器得以重启在集群中的任务。

汇总

真的可以确切地感觉到这些所有的零零散散的东西聚集到一起就是为了.NET和C#可以提供一个现代的跨平台的开发平台。我真的很高兴能继续前进,然后可以在TRAFI里可以应用这样的新的工作流(.NET Core Docker AWS 容器服务)于生产环境。

当然,这只是一个Hello World应用-它仍然处于早期阶段,当构建大型应用的时候这有可能出现一些问题。但随着当前RC2的发布,它应该已经更确定地为生产环境准备好了,并且1.0的版本会在不就得将来到来(这里是规划)。一般情况下,Microsoft似乎真的致力于新的方向,新的社区也看起来越来越壮大,看上去这些事情只会变得越来越好。

参考



请记住,大多数的信息是很新的,并且在去年一年中有很多事情在开发的时候发生了变化,包括命名(例如ASP.NET 5到 ASP.NET Core,并且打破了API的变化。不过它现在终于变得稳定了,但目前来看仍然有很多过时了的文档和教程。

原文链接:Running .NET Core on Docker(翻译:薛开成)